diff --git a/AUTHORS b/AUTHORS index 3adf4ae..fc2712f 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -654,6 +654,8 @@ Jinfeng Ma <majinfeng1@xiaomi.com> Jing Zhao <zhaojing7@xiaomi.com> Jinglong Zuo <zuojinglong@xiaomi.com> +Jingqi Sun <sunjingqi47@gmail.com> +Jingqi Sun <jingqi.sun@hotmail.com> Jingwei Liu <kingweiliu@gmail.com> Jingyi Wei <wjywbs@gmail.com> Jinho Bang <jinho.bang@samsung.com>
diff --git a/DEPS b/DEPS index d6279c0..31c2e3cd 100644 --- a/DEPS +++ b/DEPS
@@ -308,23 +308,23 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'f5dce23de2e76a39aeabd5418dfcda30b6c8106a', + 'src_internal_revision': '12652b92c8a9ff5daaf5f8d692569028e59cda05', # 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': 'd7f79d7183cdc523e79aaac9a6b2a3da11954631', + 'skia_revision': 'fef9f270935c1b1e8cc881978d510b4a5d13fdc9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '37e4bb8df182b508cc2df84abd7ef2bd64a5749e', + 'v8_revision': 'ead5cccdb1ce2bbdb2cb0b09ec66573fc9e371e3', # 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': '51c580031adcab9ab6c5c719fd92b9ba4e591ef5', + 'angle_revision': 'cc770518b07ce9ef45cd1c283e9f69b3711d304e', # 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': '764410d4d65546fd1e536b02059b1f714a390720', + 'swiftshader_revision': '9aec4b969291f0a218b537f44f8a1387cf494316', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -403,7 +403,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': '1b37ee54c6d14d87ca3aa3e38b9fd65957fc162f', + 'devtools_frontend_revision': '6a303cbb86cd070e504f3728d314430f17b4e53d', # 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. @@ -435,7 +435,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. - 'ios_webkit_revision': '59e9de61b7b36507836fa8b098e8839d7d995b13', + 'ios_webkit_revision': 'f8c0fe750d94b7db23d193c0b1f31858c2537620', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libexpat # and whatever else without interference from each other. @@ -801,7 +801,7 @@ }, 'src/chrome/test/data/password/captured_sites/artifacts': { - 'url': Var('chrome_git') + '/chrome/test/captured_sites/password.git' + '@' + 'd8bb2ef5c0ebff18c66f02e534a3f20bef7d55f5', + 'url': Var('chrome_git') + '/chrome/test/captured_sites/password.git' + '@' + '9c7a49bc3fe9540bc90520a74a77b5f99c3664a9', 'condition': 'checkout_chromium_password_manager_test_dependencies', }, @@ -827,12 +827,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - 'bce889557aaf353bc3e2b00592df54a5fc4d0db0', + '4799cd305fe7062e4a6e9b455b2bb2c4db50060d', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'fe917d70bbd8c9902b8d1fe751958a6cc55c86b4', + 'url': Var('chromium_git') + '/website.git' + '@' + 'c50bcc04d18f45a37e8b7aca67e712d20bf145c2', }, 'src/ios/third_party/earl_grey2/src': { @@ -982,7 +982,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'zCMJ2QMWoul-sgpcEzskxEzm8cPovJAL18Uai3fWHlAC', + 'version': 'uG5mZUXGcnn0JQiovIHkaxoRszRRnVnHNGrQfcredVQC', }, ], 'condition': 'checkout_android', @@ -1042,7 +1042,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'kt0D0n2B3KP5Ptno-stWIuNnhvCfms_w-8iZrMgSS8sC', + 'version': 'f5ptuXixKwddKw0rnCKuNjXY9E35_710E7SNxoOLNnMC', }, ], 'condition': 'checkout_android', @@ -1053,7 +1053,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'q4q38FXedJ-uNPtYpwR--VhUglwaiG95Nz1aNXyOL9gC', + 'version': 'Xef4nLhp0rWWjXJXt9CTFjQF8S6qRduSY7LZCcJi48QC', }, ], 'condition': 'checkout_android', @@ -1157,7 +1157,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' + '@' + '8af906338f6c07813067abf296170c8a4f46c538', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '3db9d50f201adfc9c0e567d8c7c763f91231579f', 'condition': 'checkout_chromeos', }, @@ -1192,13 +1192,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6aaae85821254406042a11254d49b14c9d1b44f3', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1a61eb625d4b062bb2d6f0902b4979b48def4d33', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'b70ff80eb2b57e077d19ced22f77faf61212b7c0', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '2829e054a8419e6ecf6d60eb321ca8511317d3f2', 'condition': 'checkout_src_internal', }, @@ -1531,7 +1531,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '8762f5efb2917765316a198e6713f0bc93b07c9b', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '85dafa9c61f99330f484e77297684b42af6ff37d', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', @@ -1811,7 +1811,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@aa20d192b8c4e4a617d93d809cc416e0429acacd', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@707349d2ea9e104986b12655c944c6f758a2443b', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -1848,10 +1848,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'bc3c8bad295ae0ba7f0ddb18848df70f92a820c0', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '48e5f9383b4c9c94a46563c59b3049705f668096', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a2897c33ec90d37cbfefed3b3f738f785850c6bf', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '56e63097498d0ad6fe2eca779b7df173cc6a0fca', + Var('webrtc_git') + '/src.git' + '@' + 'ff54aee9ab3d5fc5ea6f9d12fb05c582115b736d', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1985,7 +1985,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'tX5EJQ1TlaqN-BaDUAHJ-JgOCALXI5p2m9a91Aj5KA4C', + 'version': 'Lat_x7b35cFXCV98OfzSjnYkB1zvL40Y7DEp0c0TJsAC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3854,7 +3854,7 @@ # Dependencies from src_internal 'src/chromeos/ash/resources/internal': { 'url': Var('chrome_git') + '/chrome/chromeos/ash/resources/internal.git' + '@' + - 'a58ffb4694b2b0be123300e533578ed96aabcb5a', + '3a961174a24cfda9e444f54e3f1c783f75838b41', 'condition': 'checkout_src_internal and checkout_chromeos', }, @@ -3983,7 +3983,7 @@ # grepping. 'src/chrome/installer/mac/internal': { 'url': Var('chrome_git') + '/chrome/installer/mac/internal.git' + '@' + - '61d619941db56cde7aaec67bd10e3b4277576404', + '41badb00eefc7b698e126870555c1cb65d1acfdb', 'condition': 'checkout_src_internal', }, @@ -4125,7 +4125,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '19173a1be09e94cc26a29eff04a8c70fc59699fb', + '753730eaf49d6dd766d2dc2d1b3b0eaf83a3ec1a', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 5b8f3f44..6209837 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -42,6 +42,8 @@ r".+_pb2(_grpc)?\.py$", r".+/pnacl_shim\.c$", r"^gpu/config/.*_list_json\.cc$", + # TODO(crbug.com/332933533) Remove this exception. + r"^tools/bisect/.*", r"tools/md_browser/.*\.css$", # Test pages for Maps telemetry tests. r"tools/perf/page_sets/maps_perf_test.*", @@ -1051,6 +1053,8 @@ # Needed to use QUICHE API. r'chrome/browser/ip_protection/.*', r'services/network/web_transport.*', + # Needed to integrate with //third_party/nearby + r'components/cross_device/nearby/system_clock.cc', _THIRD_PARTY_EXCEPT_BLINK # Not an error in third_party folders. ], ), @@ -3180,38 +3184,6 @@ results.add(os_path.join(added_dep, 'DEPS')) return results -def CheckForNewDEPSDownloadFromGoogleStorageHooks(input_api, output_api): - """Checks that there are no new download_from_google_storage hooks""" - for f in input_api.AffectedFiles(include_deletes=False): - filename = input_api.os_path.basename(f.LocalPath()) - if filename == 'DEPS': - old_hooks = _ParseDeps('\n'.join(f.OldContents()))['hooks'] - new_hooks = _ParseDeps('\n'.join(f.NewContents()))['hooks'] - old_name_to_hook = {hook['name']: hook for hook in old_hooks} - new_name_to_hook = {hook['name']: hook for hook in new_hooks} - added_hook_names = set(new_name_to_hook.keys()) - set( - old_name_to_hook.keys()) - if not added_hook_names: - return [] - new_download_from_google_storage_hooks = [] - for new_hook in added_hook_names: - hook = new_name_to_hook[new_hook] - action_cmd = hook['action'] - if any('download_from_google_storage' in arg - for arg in action_cmd): - new_download_from_google_storage_hooks.append(new_hook) - if new_download_from_google_storage_hooks: - return [ - output_api.PresubmitError( - 'Please do not add new download_from_google_storage ' - 'hooks. Instead, add a `gcs` dep_type entry to `deps`. ' - 'See https://chromium.googlesource.com/chromium/src.git' - '/+/refs/heads/main/docs/gcs_dependencies.md for more ' - 'info. Added hooks:', - items=new_download_from_google_storage_hooks) - ] - return [] - def CheckAddedDepsHaveTargetApprovals(input_api, output_api): """When a dependency prefixed with + is added to a DEPS file, we @@ -3742,6 +3714,7 @@ affected_file, files_to_skip=(_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP + ( r'^build/android/devil_chromium\.py', + r'^tools/bisect/.*', r'^third_party/.*', )), files_to_check=[r'.*\.py$'])
diff --git a/WATCHLISTS b/WATCHLISTS index 47a5695..2664dce 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -806,22 +806,24 @@ }, 'chromeos_bluetooth': { 'filepath': 'ash/system/bluetooth/'\ + '|ash/webui/common/resources/bluetooth/'\ '|chromeos/ash/components/hid_detection/'\ '|chromeos/ash/services/bluetooth_config/'\ - '|chrome/browser/ui/webui/ash/bluetooth'\ '|chrome/browser/resources/ash/settings/os_bluetooth_page/'\ '|chrome/browser/resources/chromeos/bluetooth_pairing_dialog/'\ + '|chrome/browser/ui/webui/ash/bluetooth'\ '|chrome/test/data/webui/cr_components/chromeos/bluetooth/'\ '|device/bluetooth/bluez/'\ '|device/bluetooth/chromeos/'\ '|device/bluetooth/floss/'\ - '|ash/webui/common/resources/bluetooth/' + '|tools/metrics/histograms/metadata/bluetooth/' }, 'chromeos_cellular': { - 'filepath': 'chromeos/ash/services/cellular_setup/|'\ + 'filepath': 'ash/webui/common/resources/cellular_setup/'\ + 'chromeos/ash/services/cellular_setup/|'\ + 'chromeos/ash/components/carrier_lock/|'\ 'chromeos/ash/components/dbus/hermes/|'\ - 'chrome/test/data/webui/cr_components/chromeos/cellular_setup/|'\ - 'ash/webui/common/resources/cellular_setup/', + 'chrome/test/data/webui/cr_components/chromeos/cellular_setup/', }, 'chromeos_geolocation': { 'filepath': 'chromeos/ash/components/geolocation/', @@ -842,6 +844,7 @@ }, 'chromeos_net': { 'filepath': 'ash/system/network/|'\ + 'ash/webui/common/resources/hotspot/|'\ 'ash/webui/common/resources/network/|'\ 'chrome/browser/ash/net/|'\ 'chrome/browser/extensions/api/networking_private/|'\ @@ -855,11 +858,13 @@ 'chromeos/ash/components/dbus/shill/|'\ 'chromeos/ash/components/network/|'\ 'chromeos/ash/components/wifi_p2p/|'\ + 'chromeos/ash/services/hotspot_config/|'\ 'chromeos/ash/services/network_config/|'\ 'chromeos/ash/services/wifi_direct/|'\ 'chromeos/services/network_config/|'\ 'components/onc/|'\ - 'extensions/browser/api/networking_private/', + 'extensions/browser/api/networking_private/'\ + 'tools/metrics/histograms/metadata/network/', }, 'chromeos_tast_control': { 'filepath': 'chromeos/tast_control.gni', @@ -2742,9 +2747,7 @@ 'chromedriver': ['mathias@chromium.org'], 'chromeos': ['oshima+watch@chromium.org'], 'chromeos_attestation': ['dkrahn+watch@chromium.org'], - 'chromeos_bluetooth': ['andrewdear+watch-bluetooth@google.com', - 'azeemarshad+watch-bluetooth@chromium.org', - 'chadduffin+watch-bluetooth@chromium.org', + 'chromeos_bluetooth': ['chadduffin+watch-bluetooth@chromium.org', 'gordonseto+watch-bluetooth@google.com', 'hansberry+watch-bluetooth@chromium.org', 'hsuregan+watch-bluetooth@chromium.org', @@ -2753,15 +2756,13 @@ 'khorimoto+watch-bluetooth@chromium.org', 'nikhilcn+watch-bluetooth@google.com', 'tjohnsonkanu+watch-bluetooth@google.com'], - 'chromeos_cellular': ['andrewdear+watch-cellular@google.com', - 'azeemarshad+watch-cellular@chromium.org', - 'chadduffin+watch-cellular@chromium.org', + 'chromeos_cellular': ['chadduffin+watch-cellular@chromium.org', 'ejcaruso+watch-cellular@chromium.org', 'gordonseto+watch-cellular@google.com', 'hsuregan+watch-cellular@chromium.org', 'jiajunz+watch-cellular@google.com', 'khorimoto+watch-cellular@chromium.org', - 'nikhilcn+watch-cellular@google.com', + 'nikhilcn@google.com', 'tjohnsonkanu+watch-cellular@google.com'], 'chromeos_geolocation': ['alemate+watch@chromium.org'], 'chromeos_lkgm': ['achuith+watch@chromium.org'], @@ -2769,9 +2770,7 @@ 'tbarzic+watch@chromium.org', 'rrsilva+watch-chromium@google.com'], 'chromeos_media_app': ['cros-essential-apps-dev-watch@chromium.org'], - 'chromeos_net': ['andrewdear+watch-network@google.com', - 'azeemarshad+watch-network@chromium.org', - 'chadduffin+watch-network@chromium.org', + 'chromeos_net': ['chadduffin+watch-network@chromium.org', 'ejcaruso+watch-network@chromium.org', 'gordonseto+watch-network@google.com', 'hsuregan+watch-network@chromium.org', @@ -2779,7 +2778,7 @@ 'jiajunz+watch-network@google.com', 'jonmann+watch-network@chromium.org', 'khorimoto+watch-network@chromium.org', - 'nikhilcn+watch-network@google.com', + 'nikhilcn@google.com', 'stevenjb+watch-network@chromium.org', 'tjohnsonkanu+watch-network@google.com'], 'chromeos_tast_control': ['chromeos-engprod+watch@google.com',
diff --git a/android_webview/browser/state_serializer.cc b/android_webview/browser/state_serializer.cc index 52873fff..fc61440 100644 --- a/android_webview/browser/state_serializer.cc +++ b/android_webview/browser/state_serializer.cc
@@ -161,17 +161,15 @@ pickle->WriteString(entry.GetBaseURLForDataURL().spec()); if (state_version >= internal::AW_STATE_VERSION_DATA_URL) { - const char* data = nullptr; - size_t size = 0; + std::string_view view; const scoped_refptr<const base::RefCountedString>& s = entry.GetDataURLAsString(); if (s) { - data = s->front_as<char>(); - size = s->size(); + view = base::as_string_view(*s); } // Even when |entry.GetDataForDataURL()| is null we still need to write a // zero-length entry to ensure the fields all line up when read back in. - pickle->WriteData(data, size); + pickle->WriteData(view.data(), view.size()); } pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent())); @@ -316,7 +314,7 @@ return false; if (size > 0) { scoped_refptr<base::RefCountedString> ref = new base::RefCountedString(); - ref->data().assign(data, size); + ref->as_string().assign(data, size); entry->SetDataURLAsString(ref); } }
diff --git a/android_webview/browser/state_serializer_unittest.cc b/android_webview/browser/state_serializer_unittest.cc index 7a999d0..cdb3d70 100644 --- a/android_webview/browser/state_serializer_unittest.cc +++ b/android_webview/browser/state_serializer_unittest.cc
@@ -52,7 +52,7 @@ entry->SetBaseURLForDataURL(base_url_for_data_url); { scoped_refptr<base::RefCountedString> s = new base::RefCountedString(); - s->data().assign(data_url_as_string); + s->as_string() = data_url_as_string; entry->SetDataURLAsString(s); } entry->SetIsOverridingUserAgent(is_overriding_user_agent); @@ -138,8 +138,8 @@ EXPECT_EQ(entry->GetHasPostData(), copy->GetHasPostData()); EXPECT_EQ(entry->GetOriginalRequestURL(), copy->GetOriginalRequestURL()); EXPECT_EQ(entry->GetBaseURLForDataURL(), copy->GetBaseURLForDataURL()); - EXPECT_EQ(entry->GetDataURLAsString()->data(), - copy->GetDataURLAsString()->data()); + EXPECT_EQ(entry->GetDataURLAsString()->as_string(), + copy->GetDataURLAsString()->as_string()); EXPECT_EQ(entry->GetIsOverridingUserAgent(), copy->GetIsOverridingUserAgent()); EXPECT_EQ(entry->GetTimestamp(), copy->GetTimestamp()); @@ -278,7 +278,7 @@ huge_data_url.replace(0, strlen(url::kDataScheme), url::kDataScheme); { scoped_refptr<base::RefCountedString> s = new base::RefCountedString(); - s->data().assign(huge_data_url); + s->as_string().assign(huge_data_url); entry->SetDataURLAsString(s); } @@ -293,7 +293,7 @@ bool result = internal::RestoreNavigationEntryFromPickle( &iterator, copy.get(), context.get()); EXPECT_TRUE(result); - EXPECT_EQ(huge_data_url, copy->GetDataURLAsString()->data()); + EXPECT_EQ(huge_data_url, copy->GetDataURLAsString()->as_string()); } } // namespace android_webview
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 8626d68..35cb8e1 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -995,6 +995,8 @@ "picker/search/picker_category_search.h", "picker/search/picker_date_search.cc", "picker/search/picker_date_search.h", + "picker/search/picker_editor_search.cc", + "picker/search/picker_editor_search.h", "picker/search/picker_math_search.cc", "picker/search/picker_math_search.h", "picker/search/picker_search_aggregator.cc", @@ -1387,6 +1389,8 @@ "style/rounded_label.h", "style/rounded_label_widget.cc", "style/rounded_label_widget.h", + "style/rounded_rect_cutout_path_builder.cc", + "style/rounded_rect_cutout_path_builder.h", "style/sparkle_colors.cc", "style/sparkle_colors.h", "style/style_util.cc", @@ -1394,6 +1398,7 @@ "style/style_viewer/checkbox_group_instances_grid_view_factory.cc", "style/style_viewer/checkbox_instances_grid_view_factory.cc", "style/style_viewer/combobox_instances_grid_view_factory.cc", + "style/style_viewer/cutout_instances_grid_view_factory.cc", "style/style_viewer/icon_button_instances_grid_view_factory.cc", "style/style_viewer/pagination_instances_grid_view_factory.cc", "style/style_viewer/pill_button_instances_grid_view_factory.cc", @@ -3668,6 +3673,7 @@ "picker/picker_paste_request_unittest.cc", "picker/search/picker_category_search_unittest.cc", "picker/search/picker_date_search_unittest.cc", + "picker/search/picker_editor_search_unittest.cc", "picker/search/picker_math_search_unittest.cc", "picker/search/picker_search_aggregator_unittest.cc", "picker/search/picker_search_controller_unittest.cc", @@ -3753,6 +3759,7 @@ "style/color_palette_controller_unittest.cc", "style/color_util_unittest.cc", "style/dark_light_mode_controller_unittests.cc", + "style/rounded_rect_cutout_path_builder_unittest.cc", "style/system_components_unittests.cc", "style/system_shadow_unittest.cc", "system/accessibility/accessibility_detailed_view_unittest.cc",
diff --git a/ash/capture_mode/capture_mode_behavior.cc b/ash/capture_mode/capture_mode_behavior.cc index cf34068..1034c43 100644 --- a/ash/capture_mode/capture_mode_behavior.cc +++ b/ash/capture_mode/capture_mode_behavior.cc
@@ -191,15 +191,11 @@ // CaptureModeBehavior: void AttachToSession() override { - CaptureModeController* controller = CaptureModeController::Get(); - - did_ever_start_with_camera_ |= - controller->camera_controller()->selected_camera().is_valid(); - cached_configs_ = GetCaptureModeSessionConfigs(); SetCaptureModeSessionConfigs(capture_mode_configs_); + CaptureModeController* controller = CaptureModeController::Get(); BaseCaptureModeSession* session = controller->capture_mode_session(); CHECK(session); if (!pre_selected_window_) { @@ -236,7 +232,9 @@ bool ShouldGifBeSupported() const override { return false; } bool ShouldShowUserNudge() const override { return false; } bool ShouldAutoSelectFirstCamera() const override { - return !did_ever_start_with_camera_; + return !CaptureModeController::Get() + ->camera_controller() + ->did_user_ever_change_camera(); } std::unique_ptr<CaptureModeBarView> CreateCaptureModeBarView() override { @@ -293,12 +291,6 @@ int GetCaptureBarWidth() const override { return kGameCaptureBarWidth; } private: - // We only auto-select the first available camera (if none is selected) only - // if no Game Dashboard-initiated sessions ever started with a camera - // selection. Once a session starts with a camera on, all subsequent sessions - // will just continue using the most recent system-wide camera selection. - bool did_ever_start_with_camera_ = false; - raw_ptr<aura::Window> pre_selected_window_ = nullptr; base::WeakPtrFactory<GameDashboardBehavior> weak_ptr_factory_{this}; };
diff --git a/ash/capture_mode/capture_mode_camera_controller.cc b/ash/capture_mode/capture_mode_camera_controller.cc index e2de8df8..8a053f5 100644 --- a/ash/capture_mode/capture_mode_camera_controller.cc +++ b/ash/capture_mode/capture_mode_camera_controller.cc
@@ -455,7 +455,8 @@ return std::string(); } -void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id) { +void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id, + bool by_user) { // When cameras are disabled by policy, we don't allow any camera selection. if (IsCameraDisabledByPolicy()) { LOG(WARNING) << "Camera is disabled by policy. Selecting camera: " @@ -466,6 +467,13 @@ if (selected_camera_ == camera_id) return; + did_user_ever_change_camera_ |= by_user; + + // If camera auto-selection is on, and a camera change happened (either by + // user or due to disconnection), calling `MaybeRevertAutoCameraSelection()` + // should be a no-op, and the camera should not be restored to off. + did_make_camera_auto_selection_ = false; + selected_camera_ = std::move(camera_id); camera_reconnect_timer_.Stop();
diff --git a/ash/capture_mode/capture_mode_camera_controller.h b/ash/capture_mode/capture_mode_camera_controller.h index e955eef..7af2b7c 100644 --- a/ash/capture_mode/capture_mode_camera_controller.h +++ b/ash/capture_mode/capture_mode_camera_controller.h
@@ -163,6 +163,9 @@ bool is_camera_preview_collapsed() const { return is_camera_preview_collapsed_; } + bool did_user_ever_change_camera() const { + return did_user_ever_change_camera_; + } void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -185,8 +188,9 @@ // Sets the currently selected camera to the whose ID is the given // `camera_id`. If `camera_id` is invalid (see CameraId::is_valid()), this - // clears the selected camera. - void SetSelectedCamera(CameraId camera_id); + // clears the selected camera. `by_user` is true if the selection was made + // explicitly by the user, false otherwise. + void SetSelectedCamera(CameraId camera_id, bool by_user = false); // Sets `should_show_preview_` to the given `value`, and refreshes the state // of the camera preview. @@ -426,6 +430,10 @@ // selection. bool did_make_camera_auto_selection_ = false; + // True if the user ever made an explicit camera selection (i.e. from the + // capture mode settings menu). + bool did_user_ever_change_camera_ = false; + base::WeakPtrFactory<CaptureModeCameraController> weak_ptr_factory_{this}; };
diff --git a/ash/capture_mode/capture_mode_game_dashboard_unittests.cc b/ash/capture_mode/capture_mode_game_dashboard_unittests.cc index 0c32c0b5..eba5949 100644 --- a/ash/capture_mode/capture_mode_game_dashboard_unittests.cc +++ b/ash/capture_mode/capture_mode_game_dashboard_unittests.cc
@@ -702,6 +702,11 @@ ? AudioRecordingMode::kSystemAndMicrophone : AudioRecordingMode::kMicrophone); + auto* camera_controller = controller->camera_controller(); + ASSERT_TRUE(camera_controller->camera_preview_widget()); + const CameraId camera_id(kDefaultCameraModelId, 1); + EXPECT_EQ(camera_id, camera_controller->selected_camera()); + // Update the audio recording mode and demo tools configs for the // game-dashboard initiated capture mode. controller->SetAudioRecordingMode(AudioRecordingMode::kOff); @@ -728,7 +733,6 @@ // Verify that selfie camera is visible and is parented correctly to the game // window. - const auto* camera_controller = controller->camera_controller(); const auto* camera_preview_widget = camera_controller->camera_preview_widget(); ASSERT_TRUE(camera_preview_widget); @@ -797,6 +801,40 @@ EXPECT_TRUE(camera_controller->camera_preview_widget()); const CameraId camera_id(kDefaultCameraModelId, 1); EXPECT_EQ(camera_id, camera_controller->selected_camera()); + controller->Stop(); + + // The next Game Dashboard session should still launch with a camera. + StartGameCaptureModeSession(); + EXPECT_TRUE(camera_controller->camera_preview_widget()); + EXPECT_EQ(camera_id, camera_controller->selected_camera()); +} + +TEST_F(GameDashboardCaptureModeTest, CameraAutoSelectionDisabledOnChange) { + const std::string device_id_1 = "/dev/video0"; + const std::string display_name_1 = "Integrated Webcam"; + + const std::string device_id_2 = "/dev/video1"; + const std::string display_name_2 = "Integrated Webcam 1"; + + AddFakeCamera(device_id_1, display_name_1, display_name_1); + AddFakeCamera(device_id_2, display_name_2, display_name_2); + + // The first Game Dashboard session, the first camera will be auto selected. + auto* controller = StartGameCaptureModeSession(); + auto* camera_controller = controller->camera_controller(); + EXPECT_TRUE(camera_controller->camera_preview_widget()); + const CameraId camera_id1(display_name_1, 1); + EXPECT_EQ(camera_id1, camera_controller->selected_camera()); + + // Now, simulate a change by the user to select a different camera while the + // session is still running. + const CameraId camera_id2(display_name_2, 1); + camera_controller->SetSelectedCamera(camera_id2); + EXPECT_EQ(camera_id2, camera_controller->selected_camera()); + + // Stop the session and expect that the camera remains selected. + controller->Stop(); + EXPECT_EQ(camera_id2, camera_controller->selected_camera()); } TEST_F(GameDashboardCaptureModeTest, NoDimmingOfGameDashboardWidgets) {
diff --git a/ash/capture_mode/capture_mode_settings_view.cc b/ash/capture_mode/capture_mode_settings_view.cc index 9420dd2..5da993b 100644 --- a/ash/capture_mode/capture_mode_settings_view.cc +++ b/ash/capture_mode/capture_mode_settings_view.cc
@@ -363,14 +363,14 @@ controller->SetUsesDefaultCaptureFolder(false); break; case kCameraOff: - camera_controller->SetSelectedCamera(CameraId()); + camera_controller->SetSelectedCamera(CameraId(), /*by_user=*/true); break; default: DCHECK(!camera_controller->IsCameraDisabledByPolicy()); DCHECK_GE(option_id, kCameraDevicesBegin); const CameraId* camera_id = FindCameraIdByOptionId(option_id); DCHECK(camera_id); - camera_controller->SetSelectedCamera(*camera_id); + camera_controller->SetSelectedCamera(*camera_id, /*by_user=*/true); break; } }
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 93a60bf..c0738f3 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -2130,7 +2130,7 @@ // Enables or disables the OOBE QuickStart flow. BASE_FEATURE(kOobeQuickStart, "OobeQuickStart", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables or disables the OOBE QuickStart flow on the login screen. BASE_FEATURE(kOobeQuickStartOnLoginScreen, @@ -2646,11 +2646,6 @@ "ShimlessRMAComplianceCheck", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables or disables SKU description in the Shimless RMA flow. -BASE_FEATURE(kShimlessRMASkuDescription, - "ShimlessRMASkuDescription", - base::FEATURE_ENABLED_BY_DEFAULT); - // Enables 3p diagnostics in the Shimless RMA flow. BASE_FEATURE(kShimlessRMA3pDiagnostics, "ShimlessRMA3pDiagnostics", @@ -3210,14 +3205,14 @@ return base::FeatureList::IsEnabled(kAmbientModeThrottleAnimation); } -bool IsApnPoliciesEnabled() { - return base::FeatureList::IsEnabled(kApnPolicies); -} - bool IsApnRevampEnabled() { return base::FeatureList::IsEnabled(kApnRevamp); } +bool IsApnPoliciesEnabled() { + return IsApnRevampEnabled() && base::FeatureList::IsEnabled(kApnPolicies); +} + bool IsAppNotificationsPageEnabled() { return base::FeatureList::IsEnabled(kOsSettingsAppNotificationsPage); } @@ -4384,10 +4379,6 @@ return base::FeatureList::IsEnabled(kShimlessRMAComplianceCheck); } -bool IsShimlessRMASkuDescriptionEnabled() { - return base::FeatureList::IsEnabled(kShimlessRMASkuDescription); -} - bool IsShimlessRMA3pDiagnosticsEnabled() { return base::FeatureList::IsEnabled(kShimlessRMA3pDiagnostics); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 72f38b8..5d0dbc6 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -804,7 +804,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kShimlessRMAComplianceCheck); COMPONENT_EXPORT(ASH_CONSTANTS) -BASE_DECLARE_FEATURE(kShimlessRMASkuDescription); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kShimlessRMA3pDiagnostics); COMPONENT_EXPORT(ASH_CONSTANTS) @@ -1280,7 +1279,6 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShelfLauncherNudgeEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShelfStackedHotseatEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMAComplianceCheckEnabled(); -COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMASkuDescriptionEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSimLockPolicyEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMAOsUpdateEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsShimlessRMA3pDiagnosticsEnabled();
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc index 5dfffc11..58432ef 100644 --- a/ash/login/ui/login_user_view.cc +++ b/ash/login/ui/login_user_view.cc
@@ -111,7 +111,7 @@ AnimationFrames frames_; }; -class EnterpriseBadgeLayout : public views::LayoutManager { +class EnterpriseBadgeLayout : public views::LayoutManagerBase { public: explicit EnterpriseBadgeLayout(int size) : size_(size) {} @@ -120,18 +120,23 @@ ~EnterpriseBadgeLayout() override = default; - // views::LayoutManager: - void Layout(views::View* host) override { - DCHECK_EQ(host->children().size(), 1U); - const gfx::Rect content_bounds(host->GetContentsBounds()); - const int offset = content_bounds.width() - size_; - auto* child = host->children()[0].get(); - child->SetPosition({offset, offset}); - child->SetSize({size_, size_}); - } + // views::LayoutManagerBase: + views::ProposedLayout CalculateProposedLayout( + const views::SizeBounds& size_bounds) const override { + DCHECK_EQ(host_view()->children().size(), 1U); + views::ProposedLayout layout; + layout.host_size = gfx::Size(size_, size_); + if (!size_bounds.is_fully_bounded()) { + return layout; + } - gfx::Size GetPreferredSize(const views::View* host) const override { - return gfx::Size(size_, size_); + const int offset = + size_bounds.width().value() - host_view()->GetInsets().width() - size_; + auto* child = host_view()->children()[0].get(); + layout.child_layouts.emplace_back(child, true, + gfx::Rect(offset, offset, size_, size_)); + + return layout; } private:
diff --git a/ash/picker/model/picker_search_results_section.h b/ash/picker/model/picker_search_results_section.h index 956c303..ad93abc8 100644 --- a/ash/picker/model/picker_search_results_section.h +++ b/ash/picker/model/picker_search_results_section.h
@@ -23,6 +23,7 @@ kGifs, kRecentlyUsed, kExamples, + kEditor, }; // Search results are divided into different sections.
diff --git a/ash/picker/picker_controller.cc b/ash/picker/picker_controller.cc index 3dbcdcd..15deafc 100644 --- a/ash/picker/picker_controller.cc +++ b/ash/picker/picker_controller.cc
@@ -178,7 +178,11 @@ }, [](const PickerSearchResult::SearchRequestData& data) -> ReturnType { return std::monostate(); - }}, + }, + [](const PickerSearchResult::EditorData& data) -> ReturnType { + return std::monostate(); + }, + }, result.data()); } @@ -453,9 +457,11 @@ ui::EmojiPickerFocusBehavior::kAlwaysShow); } -void PickerController::ShowEditor() { +void PickerController::ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) { if (!show_editor_callback_.is_null()) { - std::move(show_editor_callback_).Run(); + std::move(show_editor_callback_) + .Run(std::move(preset_query_id), std::move(freeform_text)); } }
diff --git a/ash/picker/picker_controller.h b/ash/picker/picker_controller.h index 6d1a491..7aea8a0 100644 --- a/ash/picker/picker_controller.h +++ b/ash/picker/picker_controller.h
@@ -84,7 +84,8 @@ SearchResultsCallback callback) override; void InsertResultOnNextFocus(const PickerSearchResult& result) override; void ShowEmojiPicker(ui::EmojiPickerCategory category) override; - void ShowEditor() override; + void ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) override; void SetCapsLockEnabled(bool enabled) override; PickerAssetFetcher* GetAssetFetcher() override; @@ -107,7 +108,9 @@ std::unique_ptr<PickerSearchController> search_controller_; std::unique_ptr<PickerClipboardProvider> clipboard_provider_; - base::OnceClosure show_editor_callback_; + base::OnceCallback<void(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text)> + show_editor_callback_; // Periodically records usage metrics based on the Standard Feature Usage // Logging (SFUL) framework.
diff --git a/ash/picker/picker_controller_unittest.cc b/ash/picker/picker_controller_unittest.cc index 8eec208..394c6bc 100644 --- a/ash/picker/picker_controller_unittest.cc +++ b/ash/picker/picker_controller_unittest.cc
@@ -39,6 +39,7 @@ namespace { using ::testing::Contains; +using ::testing::FieldsAre; using ::testing::NiceMock; using ::testing::Not; using ::testing::Return; @@ -377,14 +378,16 @@ TEST_F(PickerControllerTest, ShowEditorCallsCallbackFromClient) { PickerController controller; NiceMock<TestPickerClient> client(&controller); - base::test::TestFuture<void> show_editor_future; + base::test::TestFuture<std::optional<std::string>, std::optional<std::string>> + show_editor_future; EXPECT_CALL(client, CacheEditorContext) .WillOnce(Return(show_editor_future.GetCallback())); controller.ToggleWidget(); - controller.ShowEditor(); + controller.ShowEditor(/*preset_query_id=*/"preset", + /*freeform_text=*/"freeform"); - EXPECT_TRUE(show_editor_future.Wait()); + EXPECT_THAT(show_editor_future.Get(), FieldsAre("preset", "freeform")); } TEST_F(PickerControllerTest, AvailableCategoriesContainsEditorWhenEnabled) { @@ -393,7 +396,6 @@ EXPECT_CALL(client, CacheEditorContext).WillOnce(Return(base::DoNothing())); controller.ToggleWidget(); - controller.ShowEditor(); EXPECT_THAT(controller.GetAvailableCategories(), Contains(PickerCategory::kEditor));
diff --git a/ash/picker/search/mock_search_picker_client.cc b/ash/picker/search/mock_search_picker_client.cc index 8dcd0a7a..8fbd387 100644 --- a/ash/picker/search/mock_search_picker_client.cc +++ b/ash/picker/search/mock_search_picker_client.cc
@@ -28,7 +28,7 @@ }); ON_CALL(*this, CacheEditorContext).WillByDefault([]() { ADD_FAILURE() << "CacheEditorContext should not be called in this unittest"; - return base::OnceClosure(); + return ShowEditorCallback(); }); }
diff --git a/ash/picker/search/picker_editor_search.cc b/ash/picker/search/picker_editor_search.cc new file mode 100644 index 0000000..00e700b --- /dev/null +++ b/ash/picker/search/picker_editor_search.cc
@@ -0,0 +1,33 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/picker/search/picker_editor_search.h" + +#include <optional> +#include <string> +#include <string_view> + +#include "ash/public/cpp/picker/picker_search_result.h" +#include "base/check.h" +#include "base/strings/utf_string_conversions.h" +#include "chromeos/ash/components/string_matching/tokenized_string.h" + +namespace ash { +namespace { + +constexpr int kMinWordsNeededForEditorMatch = 4; + +} + +std::optional<PickerSearchResult> PickerEditorSearch( + std::u16string_view query) { + CHECK(!query.empty()); + string_matching::TokenizedString tokenized_query{std::u16string(query)}; + return tokenized_query.tokens().size() >= kMinWordsNeededForEditorMatch + ? std::make_optional( + PickerSearchResult::Editor(base::UTF16ToUTF8(query))) + : std::nullopt; +} + +} // namespace ash
diff --git a/ash/picker/search/picker_editor_search.h b/ash/picker/search/picker_editor_search.h new file mode 100644 index 0000000..779fee4 --- /dev/null +++ b/ash/picker/search/picker_editor_search.h
@@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_PICKER_SEARCH_PICKER_EDITOR_SEARCH_H_ +#define ASH_PICKER_SEARCH_PICKER_EDITOR_SEARCH_H_ + +#include <optional> +#include <string_view> + +#include "ash/ash_export.h" + +namespace ash { + +class PickerSearchResult; + +// `query` must not be empty. +ASH_EXPORT std::optional<PickerSearchResult> PickerEditorSearch( + std::u16string_view query); + +} // namespace ash + +#endif // ASH_PICKER_SEARCH_PICKER_CATEGORY_SEARCH_H_
diff --git a/ash/picker/search/picker_editor_search_unittest.cc b/ash/picker/search/picker_editor_search_unittest.cc new file mode 100644 index 0000000..1433e52a --- /dev/null +++ b/ash/picker/search/picker_editor_search_unittest.cc
@@ -0,0 +1,37 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/picker/search/picker_editor_search.h" + +#include <string> + +#include "ash/public/cpp/picker/picker_search_result.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash { +namespace { + +using ::testing::Eq; +using ::testing::Field; +using ::testing::Optional; +using ::testing::Property; +using ::testing::VariantWith; + +TEST(PickerEditorSearchTest, MatchesSentence) { + EXPECT_THAT( + PickerEditorSearch(u"the quick brown fox"), + Optional(Property( + "data", &PickerSearchResult::data, + VariantWith<PickerSearchResult::EditorData>(Field( + "freeform_text", &PickerSearchResult::EditorData::freeform_text, + Optional(Eq("the quick brown fox"))))))); +} + +TEST(PickerEditorSearchTest, DoesNotMatchShortSentence) { + EXPECT_EQ(PickerEditorSearch(u"the quick brown"), std::nullopt); +} + +} // namespace +} // namespace ash
diff --git a/ash/picker/search/picker_search_aggregator.cc b/ash/picker/search/picker_search_aggregator.cc index 3b12279a..a0637c42 100644 --- a/ash/picker/search/picker_search_aggregator.cc +++ b/ash/picker/search/picker_search_aggregator.cc
@@ -40,6 +40,8 @@ return PickerSectionType::kFiles; case PickerSearchSource::kDrive: return PickerSectionType::kDriveFiles; + case PickerSearchSource::kEditor: + return PickerSectionType::kEditor; } } @@ -107,6 +109,7 @@ for (PickerSectionType type : { PickerSectionType::kSuggestions, PickerSectionType::kCategories, + PickerSectionType::kEditor, PickerSectionType::kExpressions, PickerSectionType::kLinks, PickerSectionType::kFiles,
diff --git a/ash/picker/search/picker_search_aggregator_unittest.cc b/ash/picker/search/picker_search_aggregator_unittest.cc index f724a45..c3a4e93 100644 --- a/ash/picker/search/picker_search_aggregator_unittest.cc +++ b/ash/picker/search/picker_search_aggregator_unittest.cc
@@ -90,6 +90,10 @@ TestCase{ .source = PickerSearchSource::kMath, .section_type = PickerSectionType::kSuggestions, + }, + TestCase{ + .source = PickerSearchSource::kEditor, + .section_type = PickerSectionType::kEditor, })); TEST_P(PickerSearchAggregatorTest, DoesNotPublishResultsDuringBurnIn) { @@ -280,6 +284,15 @@ &PickerSearchResult::TextData::primary_text, u"category")))))), AllOf(Property("type", &PickerSearchResultsSection::type, + PickerSectionType::kEditor), + Property("results", &PickerSearchResultsSection::results, + ElementsAre(Property( + "data", &PickerSearchResult::data, + VariantWith<PickerSearchResult::TextData>(Field( + "primary_text", + &PickerSearchResult::TextData::primary_text, + u"editor")))))), + AllOf(Property("type", &PickerSearchResultsSection::type, PickerSectionType::kExpressions), Property("results", &PickerSearchResultsSection::results, ElementsAre(Property( @@ -355,6 +368,9 @@ aggregator.HandleSearchSourceResults(PickerSearchSource::kMath, {PickerSearchResult::Text(u"math")}, /*has_more_results=*/false); + aggregator.HandleSearchSourceResults(PickerSearchSource::kEditor, + {PickerSearchResult::Text(u"editor")}, + /*has_more_results=*/false); task_environment().FastForwardBy(kBurnInPeriod); } @@ -436,6 +452,18 @@ &PickerSearchResult::TextData::primary_text, u"local"))))))))) .Times(1); + EXPECT_CALL(search_results_callback, + Call(ElementsAre(AllOf( + Property("type", &PickerSearchResultsSection::type, + PickerSectionType::kEditor), + Property("results", &PickerSearchResultsSection::results, + ElementsAre(Property( + "data", &PickerSearchResult::data, + VariantWith<PickerSearchResult::TextData>(Field( + "primary_text", + &PickerSearchResult::TextData::primary_text, + u"editor"))))))))) + .Times(1); PickerSearchAggregator aggregator( kBurnInPeriod, @@ -467,6 +495,9 @@ aggregator.HandleSearchSourceResults(PickerSearchSource::kMath, {PickerSearchResult::Text(u"math")}, /*has_more_results=*/false); + aggregator.HandleSearchSourceResults(PickerSearchSource::kEditor, + {PickerSearchResult::Text(u"editor")}, + /*has_more_results=*/false); } TEST_F(PickerSearchAggregatorMultipleSourcesTest,
diff --git a/ash/picker/search/picker_search_request.cc b/ash/picker/search/picker_search_request.cc index 5ffb75b3..d84c88a 100644 --- a/ash/picker/search/picker_search_request.cc +++ b/ash/picker/search/picker_search_request.cc
@@ -14,6 +14,7 @@ #include "ash/picker/picker_clipboard_provider.h" #include "ash/picker/search/picker_category_search.h" #include "ash/picker/search/picker_date_search.h" +#include "ash/picker/search/picker_editor_search.h" #include "ash/picker/search/picker_math_search.h" #include "ash/picker/search/picker_search_source.h" #include "ash/public/cpp/app_list/app_list_types.h" @@ -113,6 +114,10 @@ // Category results are currently synchronous. HandleCategorySearchResults( PickerCategorySearch(available_categories, query)); + + // Editor results are currently synchronous. + editor_search_start_ = base::TimeTicks::Now(); + HandleEditorSearchResults(PickerEditorSearch(query)); } } @@ -314,6 +319,24 @@ /*has_more_results=*/false); } +void PickerSearchRequest::HandleEditorSearchResults( + std::optional<PickerSearchResult> result) { + if (editor_search_start_.has_value()) { + base::TimeDelta elapsed = base::TimeTicks::Now() - *editor_search_start_; + base::UmaHistogramTimes("Ash.Picker.Search.EditorProvider.QueryTime", + elapsed); + } + + std::vector<PickerSearchResult> results; + if (result.has_value()) { + results.push_back(std::move(*result)); + } + + // Editor results are never truncated. + HandleSearchSourceResults(PickerSearchSource::kEditor, std::move(results), + /*has_more_results=*/false); +} + void PickerSearchRequest::OnDriveSearchTimeout() { HandleSearchSourceResults(PickerSearchSource::kDrive, {}, /*has_more_results=*/false);
diff --git a/ash/picker/search/picker_search_request.h b/ash/picker/search/picker_search_request.h index 5dd0d73..d1ea54d 100644 --- a/ash/picker/search/picker_search_request.h +++ b/ash/picker/search/picker_search_request.h
@@ -71,6 +71,7 @@ void HandleDateSearchResults(std::vector<PickerSearchResult> results); void HandleMathSearchResults(std::optional<PickerSearchResult> result); void HandleClipboardSearchResults(std::vector<PickerSearchResult> results); + void HandleEditorSearchResults(std::optional<PickerSearchResult> result); void OnDriveSearchTimeout(); @@ -90,6 +91,7 @@ std::optional<base::TimeTicks> category_search_start_; std::optional<base::TimeTicks> math_search_start_; std::optional<base::TimeTicks> clipboard_search_start_; + std::optional<base::TimeTicks> editor_search_start_; PickerSearchDebouncer gif_search_debouncer_;
diff --git a/ash/picker/search/picker_search_request_unittest.cc b/ash/picker/search/picker_search_request_unittest.cc index f8fec0e..16c4ba1 100644 --- a/ash/picker/search/picker_search_request_unittest.cc +++ b/ash/picker/search/picker_search_request_unittest.cc
@@ -47,6 +47,7 @@ using ::testing::IsEmpty; using ::testing::IsSupersetOf; using ::testing::NiceMock; +using ::testing::Optional; using ::testing::Property; using ::testing::VariantWith; @@ -1189,5 +1190,40 @@ "Ash.Picker.Search.ClipboardProvider.QueryTime", kMetricMetricTime, 1); } +TEST_F(PickerSearchRequestTest, ShowsResultsFromEditorSearch) { + MockSearchResultsCallback search_results_callback; + EXPECT_CALL(search_results_callback, Call).Times(AnyNumber()); + EXPECT_CALL( + search_results_callback, + Call(PickerSearchSource::kEditor, + ElementsAre(Property( + "data", &PickerSearchResult::data, + VariantWith<PickerSearchResult::EditorData>(Field( + "freeform_text", + &PickerSearchResult::EditorData::freeform_text, + Optional(Eq("quick brown fox jumped over lazy dog")))))), + /*has_more_results=*/false)) + .Times(1); + + PickerSearchRequest request( + u"quick brown fox jumped over lazy dog", std::nullopt, + base::BindRepeating(&MockSearchResultsCallback::Call, + base::Unretained(&search_results_callback)), + &client(), &emoji_search(), kAllCategories); +} + +TEST_F(PickerSearchRequestTest, RecordsEditorMetrics) { + base::HistogramTester histogram; + NiceMock<MockSearchResultsCallback> search_results_callback; + + PickerSearchRequest request( + u"quick brown fox jumped over lazy dog", std::nullopt, + base::BindRepeating(&MockSearchResultsCallback::Call, + base::Unretained(&search_results_callback)), + &client(), &emoji_search(), kAllCategories); + + histogram.ExpectTotalCount("Ash.Picker.Search.EditorProvider.QueryTime", 1); +} + } // namespace } // namespace ash
diff --git a/ash/picker/search/picker_search_source.h b/ash/picker/search/picker_search_source.h index c9933139..23396598 100644 --- a/ash/picker/search/picker_search_source.h +++ b/ash/picker/search/picker_search_source.h
@@ -17,6 +17,7 @@ kDrive, kMath, kClipboard, + kEditor, }; }
diff --git a/ash/picker/views/picker_search_results_view.cc b/ash/picker/views/picker_search_results_view.cc index fe096ca4..24e04e6 100644 --- a/ash/picker/views/picker_search_results_view.cc +++ b/ash/picker/views/picker_search_results_view.cc
@@ -337,6 +337,15 @@ item_view->SetLeadingIcon(GetIconForPickerCategory(data.category)); section_view->AddListItem(std::move(item_view)); }, + [&](const PickerSearchResult::EditorData& data) { + auto item_view = std::make_unique<PickerListItemView>( + std::move(select_result_callback)); + item_view->SetPrimaryText( + GetLabelForPickerCategory(PickerCategory::kEditor)); + item_view->SetLeadingIcon( + GetIconForPickerCategory(PickerCategory::kEditor)); + section_view->AddListItem(std::move(item_view)); + }, }, result.data()); }
diff --git a/ash/picker/views/picker_strings.cc b/ash/picker/views/picker_strings.cc index 09f33db..19ea877 100644 --- a/ash/picker/views/picker_strings.cc +++ b/ash/picker/views/picker_strings.cc
@@ -124,6 +124,8 @@ return u"Recently used"; case PickerSectionType::kExamples: return u"Examples"; + case PickerSectionType::kEditor: + return u"Editor"; } }
diff --git a/ash/picker/views/picker_view.cc b/ash/picker/views/picker_view.cc index 70ea330..33993c00 100644 --- a/ash/picker/views/picker_view.cc +++ b/ash/picker/views/picker_view.cc
@@ -129,6 +129,7 @@ case PickerSectionType::kSuggestions: case PickerSectionType::kRecentlyUsed: case PickerSectionType::kExamples: + case PickerSectionType::kEditor: NOTREACHED_NORETURN(); case PickerSectionType::kExpressions: return PickerCategory::kExpressions; @@ -265,6 +266,10 @@ &result.data())) { search_field_view_->SetQueryText(search_request_data->text); StartSearch(search_request_data->text); + } else if (const PickerSearchResult::EditorData* editor_data = + std::get_if<PickerSearchResult::EditorData>(&result.data())) { + delegate_->ShowEditor(/*preset_query_id=*/std::nullopt, + editor_data->freeform_text); } else { delegate_->InsertResultOnNextFocus(result); GetWidget()->Close(); @@ -297,7 +302,9 @@ // open Editor in the correct location in some other way. widget->CloseWithReason(views::Widget::ClosedReason::kLostFocus); } - delegate_->ShowEditor(); + CHECK(query.empty()); + delegate_->ShowEditor(/*preset_query_id*/ std::nullopt, + /*freeform_text=*/std::nullopt); return; }
diff --git a/ash/picker/views/picker_view_delegate.h b/ash/picker/views/picker_view_delegate.h index 7c260b36..8b94567 100644 --- a/ash/picker/views/picker_view_delegate.h +++ b/ash/picker/views/picker_view_delegate.h
@@ -57,7 +57,8 @@ virtual void ShowEmojiPicker(ui::EmojiPickerCategory category) = 0; // Shows the Editor. - virtual void ShowEditor() = 0; + virtual void ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) = 0; // Sets the current caps lock state. virtual void SetCapsLockEnabled(bool enabled) = 0;
diff --git a/ash/picker/views/picker_view_unittest.cc b/ash/picker/views/picker_view_unittest.cc index c4c430da..1c04a03 100644 --- a/ash/picker/views/picker_view_unittest.cc +++ b/ash/picker/views/picker_view_unittest.cc
@@ -110,7 +110,10 @@ void ShowEmojiPicker(ui::EmojiPickerCategory category) override { showed_emoji_picker_ = true; } - void ShowEditor() override { showed_editor_ = true; } + void ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) override { + showed_editor_ = true; + } void SetCapsLockEnabled(bool enabled) override { caps_lock_enabled_ = enabled; }
diff --git a/ash/picker/views/picker_widget_unittest.cc b/ash/picker/views/picker_widget_unittest.cc index 9defbde..799193f 100644 --- a/ash/picker/views/picker_widget_unittest.cc +++ b/ash/picker/views/picker_widget_unittest.cc
@@ -40,7 +40,8 @@ SearchResultsCallback callback) override {} void InsertResultOnNextFocus(const PickerSearchResult& result) override {} void ShowEmojiPicker(ui::EmojiPickerCategory category) override {} - void ShowEditor() override {} + void ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) override {} void SetCapsLockEnabled(bool enabled) override {} PickerAssetFetcher* GetAssetFetcher() override { return nullptr; } };
diff --git a/ash/public/cpp/picker/picker_client.h b/ash/public/cpp/picker/picker_client.h index b171146..d819319 100644 --- a/ash/public/cpp/picker/picker_client.h +++ b/ash/public/cpp/picker/picker_client.h
@@ -32,7 +32,9 @@ using CrosSearchResultsCallback = base::RepeatingCallback<void(ash::AppListSearchResultType result_type, std::vector<PickerSearchResult> results)>; - using ShowEditorCallback = base::OnceClosure; + using ShowEditorCallback = + base::OnceCallback<void(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text)>; using RecentFilesCallback = base::OnceCallback<void(std::vector<PickerSearchResult>)>; using SuggestedLinksCallback =
diff --git a/ash/public/cpp/picker/picker_search_result.cc b/ash/public/cpp/picker/picker_search_result.cc index 176250e9..0ada6fb98 100644 --- a/ash/public/cpp/picker/picker_search_result.cc +++ b/ash/public/cpp/picker/picker_search_result.cc
@@ -86,6 +86,21 @@ bool PickerSearchResult::CategoryData::operator==(const CategoryData&) const = default; +PickerSearchResult::EditorData::EditorData( + std::optional<std::string> freeform_text) + : freeform_text(std::move(freeform_text)) {} + +PickerSearchResult::EditorData::EditorData( + const PickerSearchResult::EditorData&) = default; + +PickerSearchResult::EditorData& PickerSearchResult::EditorData::operator=( + const PickerSearchResult::EditorData&) = default; + +PickerSearchResult::EditorData::~EditorData() = default; + +bool PickerSearchResult::EditorData::operator==(const EditorData&) const = + default; + PickerSearchResult::~PickerSearchResult() = default; PickerSearchResult::PickerSearchResult(const PickerSearchResult&) = default; @@ -175,6 +190,11 @@ return PickerSearchResult(CategoryData{.category = category}); } +PickerSearchResult PickerSearchResult::Editor( + std::optional<std::string> freeform_text) { + return PickerSearchResult(EditorData(std::move(freeform_text))); +} + bool PickerSearchResult::operator==(const PickerSearchResult&) const = default; const PickerSearchResult::Data& PickerSearchResult::data() const {
diff --git a/ash/public/cpp/picker/picker_search_result.h b/ash/public/cpp/picker/picker_search_result.h index 28b09e7..f8e8ac6 100644 --- a/ash/public/cpp/picker/picker_search_result.h +++ b/ash/public/cpp/picker/picker_search_result.h
@@ -143,6 +143,17 @@ bool operator==(const CategoryData&) const; }; + struct EditorData { + std::optional<std::string> freeform_text; + + EditorData(std::optional<std::string> freeform_text); + EditorData(const EditorData&); + EditorData& operator=(const EditorData&); + ~EditorData(); + + bool operator==(const EditorData&) const; + }; + using Data = std::variant<TextData, SearchRequestData, EmojiData, @@ -153,7 +164,8 @@ BrowsingHistoryData, LocalFileData, DriveFileData, - CategoryData>; + CategoryData, + EditorData>; PickerSearchResult(const PickerSearchResult&); PickerSearchResult& operator=(const PickerSearchResult&); @@ -188,6 +200,7 @@ base::FilePath file_path); static PickerSearchResult DriveFile(std::u16string title, const GURL& url); static PickerSearchResult Category(PickerCategory category); + static PickerSearchResult Editor(std::optional<std::string> freeform_text); const Data& data() const;
diff --git a/ash/public/cpp/system/toast_data.h b/ash/public/cpp/system/toast_data.h index 3e1c6fe..e527e7d 100644 --- a/ash/public/cpp/system/toast_data.h +++ b/ash/public/cpp/system/toast_data.h
@@ -17,9 +17,11 @@ namespace ash { struct ASH_PUBLIC_EXPORT ToastData { - // A `ToastData` with a `kInfiniteDuration` duration will be displayed until - // the dismiss button on the toast is clicked. - static constexpr base::TimeDelta kInfiniteDuration = base::TimeDelta::Max(); + // A `ToastData` with a `kInfiniteDuration` duration will be displayed for 30 + // minutes or until the dismiss button on the toast is clicked. An actual + // infinite duration is not used to prevent cases where the toast won't be + // dismissable e.g. on kiosk mode that limits user input. + static constexpr base::TimeDelta kInfiniteDuration = base::Minutes(30); // The default duration that a toast will be shown before it is automatically // dismissed.
diff --git a/ash/quick_pair/repository/fast_pair/proto_conversions.cc b/ash/quick_pair/repository/fast_pair/proto_conversions.cc index 12ccbb0..95f68d05 100644 --- a/ash/quick_pair/repository/fast_pair/proto_conversions.cc +++ b/ash/quick_pair/repository/fast_pair/proto_conversions.cc
@@ -56,8 +56,7 @@ StoredDiscoveryItem_State_STATE_ENABLED); auto image_memory = device_metadata->image().As1xPNGBytes(); - std::string png_encoded_image(image_memory->front_as<char>(), - image_memory->size()); + std::string png_encoded_image(base::as_string_view(*image_memory)); discovery_item.set_icon_png(png_encoded_image); discovery_item.add_stored_relevances()->mutable_relevance()->set_evaluation(
diff --git a/ash/style/rounded_rect_cutout_path_builder.cc b/ash/style/rounded_rect_cutout_path_builder.cc new file mode 100644 index 0000000..424211e --- /dev/null +++ b/ash/style/rounded_rect_cutout_path_builder.cc
@@ -0,0 +1,334 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/rounded_rect_cutout_path_builder.h" + +#include <array> +#include <utility> + +#include "base/check_op.h" +#include "base/containers/fixed_flat_map.h" +#include "base/logging.h" +#include "third_party/skia/include/core/SkPathBuilder.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkSize.h" + +namespace ash { + +namespace { + +enum class Direction { kCounterClockwise, kClockwise }; + +class CornersSequence { + public: + // A never ending sequence of corners around a rectangle in a given + // `direction` starting at `start`. + CornersSequence(RoundedRectCutoutPathBuilder::Corner start, + Direction direction) + : direction_(direction) { + size_t i = 0; + for (; i < kOrderedCorners.size(); i++) { + if (kOrderedCorners[i] == start) { + break; + } + } + current_ = i; + } + + // Returns the current corner and advances in `direction_`. + RoundedRectCutoutPathBuilder::Corner Next() { + RoundedRectCutoutPathBuilder::Corner corner = kOrderedCorners[current_]; + current_ = NextIndex(current_, direction_); + return corner; + } + + // Returns the current corner then updates the current corner in the opposite + // of `direction_`. + RoundedRectCutoutPathBuilder::Corner Back() { + RoundedRectCutoutPathBuilder::Corner corner = kOrderedCorners[current_]; + Direction reversed_direction = direction_ == Direction::kCounterClockwise + ? Direction::kClockwise + : Direction::kCounterClockwise; + current_ = NextIndex(current_, reversed_direction); + return corner; + } + + // Returns the corner that is opposite of the current corner. + RoundedRectCutoutPathBuilder::Corner OppositeCurrent() const { + // Since this is a rectangle, the opposite corner is always 2 steps away. + return kOrderedCorners.at((current_ + 2) % 4); + } + + private: + // Corners in counterclockwise order. + static constexpr std::array<RoundedRectCutoutPathBuilder::Corner, 4> + kOrderedCorners = {RoundedRectCutoutPathBuilder::Corner::kUpperLeft, + RoundedRectCutoutPathBuilder::Corner::kLowerLeft, + RoundedRectCutoutPathBuilder::Corner::kLowerRight, + RoundedRectCutoutPathBuilder::Corner::kUpperRight}; + + int NextIndex(int current, Direction direction) const { + int index = current + (direction == Direction::kCounterClockwise + ? 1 + : kOrderedCorners.size() - 1); + return index % kOrderedCorners.size(); + } + + Direction direction_; + // Tracks the index of the current corner. + int current_; +}; + +// Returns the offset vector from the kUpperLeft to `corner` for `rect`. +// +// NOTE: Since the vector is relative to `rect`, it is independent of the origin +// of `rect`. +SkVector OffsetFromUpperLeft(RoundedRectCutoutPathBuilder::Corner corner, + const SkRect& rect) { + switch (corner) { + case RoundedRectCutoutPathBuilder::Corner::kUpperLeft: + return {0.f, 0.f}; + case RoundedRectCutoutPathBuilder::Corner::kLowerLeft: + return {0.f, rect.height()}; + case RoundedRectCutoutPathBuilder::Corner::kLowerRight: + return {rect.width(), rect.height()}; + case RoundedRectCutoutPathBuilder::Corner::kUpperRight: + return {rect.width(), 0.f}; + } +} + +// Returns the `corner` point of the `rect`. +SkPoint CornerFromRect(RoundedRectCutoutPathBuilder::Corner corner, + const SkRect& rect) { + SkPoint top_left(rect.left(), rect.top()); + return top_left + OffsetFromUpperLeft(corner, rect); +} + +// Move `rect` so that the position of `rect_corner` in `rect` matches the +// position of `view_corner` in `view`. +void MatchCorners(RoundedRectCutoutPathBuilder::Corner view_corner, + const SkRect& view, + RoundedRectCutoutPathBuilder::Corner rect_corner, + SkRect& rect) { + SkPoint new_location = CornerFromRect(view_corner, view) - + OffsetFromUpperLeft(rect_corner, rect); + rect.offsetTo(new_location.x(), new_location.y()); +} + +// Modifies `rect` so that the `corner` of `view` and `rect` match. +// e.g. If `corner` is `kBottomRight`, `rect` is moved so that the bottom right +// corner of `view` and `rect` match. +void MoveRectToCorner(RoundedRectCutoutPathBuilder::Corner corner, + const SkRect& view, + SkRect& rect) { + MatchCorners(corner, view, corner, rect); +} + +// Generates 3 rectangles (small corner, inner corner, small corner) that +// represent the bounds of the arcs for the cutout at `corner`. The cutout is +// of `cutout_size`, inscribed into `view`. Small corners have +// `outer_corner_radius` and the inner corner has `inner_corner_radius`. +// +// e.g. Corner::kLowerRight +// +// SS +// SS +// LLLLOO +// LLLLOO +// LLLLOO +// RROOOOOO +// RROOOOOO +// +// R = 1st outer corner, L = inner corner, S = 2nd outer corner, O = Remainder +// of cutout (not in rects). +std::array<SkRect, 3> PlaceRects(RoundedRectCutoutPathBuilder::Corner corner, + const SkRect& view, + const SkSize& cutout_size, + float outer_corner_radius, + float inner_corner_radius) { + // rects[0] is the first outer corner, rects[1] is the inner corner, rects[2] + // is the last outer corner. + std::array<SkRect, 3> rects = { + SkRect::MakeWH(outer_corner_radius, outer_corner_radius), + SkRect::MakeWH(inner_corner_radius, inner_corner_radius), + SkRect::MakeWH(outer_corner_radius, outer_corner_radius)}; + + SkRect cutout = SkRect::MakeSize(cutout_size); + // Place `cutout` in the appropriate corner of `view`. + MoveRectToCorner(corner, view, cutout); + + CornersSequence sequence(corner, Direction::kClockwise); + // For the cutout, corners are drawn in the opposite direction from how we + // iterate around the rectangle (because the cutouts are convex). We happen + // to draw all the corners except the corner where the cutout is located. So + // start there but skip it. + sequence.Next(); + + MatchCorners(sequence.Next(), cutout, corner, rects[0]); + MoveRectToCorner(sequence.Next(), cutout, rects[1]); + MatchCorners(sequence.Next(), cutout, corner, rects[2]); + + // This draws nonsensical curves if the corners overlap. + CHECK(!rects[1].intersect(rects[0])); + CHECK(!rects[1].intersect(rects[2])); + return rects; +} + +// Add a rounded path to `builder` for a `corner` of `rect`. The path is drawn +// counter clockwise from the corner before `corner` to the opposite corner. +// e.g. if `corner` is kUpperRight, the path is drawn from kLowerRight to +// kUpperLeft. +void AddRoundedCorner(RoundedRectCutoutPathBuilder::Corner corner, + const SkRect& rect, + SkPathBuilder& builder, + Direction direction = Direction::kCounterClockwise) { + CornersSequence sequence(corner, direction); + // The large rounded corner starts at the corner before the corner where + // it is drawn. So, backup one and discard it since we'll hit it again. + sequence.Back(); + + SkPoint start = CornerFromRect(sequence.Next(), rect); + SkPoint control_point = CornerFromRect(sequence.Next(), rect); + SkPoint end = CornerFromRect(sequence.Next(), rect); + + builder.lineTo(start); + builder.conicTo(control_point, end, SK_ScalarRoot2Over2); +} + +// Adds the required paths to `builder` to draw a the cutout of +// `cutout_size` within `view` with `outer_corner_radius` for the first two +// corners and `inner_corner_radius` for the interior corner. A line will be +// drawn to the first conic will be drawn from the location of `builder`. +// The path will end at the end of the last conic. +void AddCutoutPaths(RoundedRectCutoutPathBuilder::Corner corner, + SkPathBuilder& builder, + const SkRect& view, + const SkSize& cutout_size, + int outer_corner_radius, + int inner_corner_radius) { + // Create rectangles that enclose each of the curves. + std::array<SkRect, 3> rects = PlaceRects( + corner, view, cutout_size, outer_corner_radius, inner_corner_radius); + + // Draw the first outer corner. + AddRoundedCorner(corner, rects[0], builder); + + // The inner corner is drawn opposite from the current corner and in the + // clockwise direction because it is convex. + CornersSequence sequence(corner, Direction::kCounterClockwise); + AddRoundedCorner(sequence.OppositeCurrent(), rects[1], builder, + Direction::kClockwise); + + // Draw the other outer corner. + AddRoundedCorner(corner, rects[2], builder); +} + +} // namespace + +RoundedRectCutoutPathBuilder::RoundedRectCutoutPathBuilder(gfx::SizeF bounds) + : bounds_(bounds) { + CHECK_GE(bounds.width(), corner_radius_ * 2.f) + << "Width must be at least twice as large as corner radius"; + CHECK_GE(bounds.height(), corner_radius_ * 2.f) + << "Height must be at least twice as large as corner radius"; +} + +RoundedRectCutoutPathBuilder::RoundedRectCutoutPathBuilder( + const RoundedRectCutoutPathBuilder&) = default; +RoundedRectCutoutPathBuilder& RoundedRectCutoutPathBuilder::operator=( + const RoundedRectCutoutPathBuilder&) = default; + +RoundedRectCutoutPathBuilder::~RoundedRectCutoutPathBuilder() = default; + +RoundedRectCutoutPathBuilder& RoundedRectCutoutPathBuilder::CornerRadius( + int radius) { + corner_radius_ = radius; + return *this; +} + +RoundedRectCutoutPathBuilder& RoundedRectCutoutPathBuilder::AddCutout( + RoundedRectCutoutPathBuilder::Corner corner, + gfx::SizeF size) { + if (size.IsZero()) { + cutouts_.erase(corner); + return *this; + } + + // Cutouts must be less than half the size of the view so that they don't + // overlap. + CHECK_GE(bounds_.width(), size.width() * 2.f) + << "Cutout width is too large for shape"; + CHECK_GE(bounds_.height(), size.height() * 2.f) + << "Cutout height is too large for shape"; + + cutouts_[corner] = size; + return *this; +} + +RoundedRectCutoutPathBuilder& +RoundedRectCutoutPathBuilder::CutoutInnerCornerRadius(int radius) { + cutout_inner_corner_radius_ = radius; + return *this; +} + +RoundedRectCutoutPathBuilder& +RoundedRectCutoutPathBuilder::CutoutOuterCornerRadius(int radius) { + cutout_outer_corner_radius_ = radius; + return *this; +} + +SkPath RoundedRectCutoutPathBuilder::Build() { + SkRect view = SkRect::MakeWH(bounds_.width(), bounds_.height()); + CHECK_GE(view.width(), corner_radius_ * 2.f) + << "Width must be at least twice as large as corner radius"; + CHECK_GE(view.height(), corner_radius_ * 2.f) + << "Height must be at least twice as large as corner radius"; + + SkPathBuilder builder; + // Start at the top center of the rectangle. + builder.moveTo(view.width() / 2.f, view.top()); + + // Build paths counter clockwise around view. + CornersSequence around(RoundedRectCutoutPathBuilder::Corner::kUpperLeft, + Direction::kCounterClockwise); + RoundedRectCutoutPathBuilder::Corner cur_corner = around.Next(); + do { + auto iter = cutouts_.find(cur_corner); + if (iter != cutouts_.end()) { + // Adds the paths for the cutout. + gfx::SizeF size = iter->second; + CHECK_GE(bounds_.width(), + (size.width() + cutout_outer_corner_radius_) * 2.f) + << "Cutout width + outer corner radius must be less than half of " + "bounds width"; + CHECK_GE(bounds_.height(), + (size.height() + cutout_outer_corner_radius_) * 2.f) + << "Cutout height + outer corner radius must be less than half of " + "bounds height"; + + AddCutoutPaths(cur_corner, builder, view, + SkSize::Make(size.width(), size.height()), + cutout_outer_corner_radius_, cutout_inner_corner_radius_); + } else { + if (corner_radius_ == 0) { + // If corner radius is 0, it's a point so just draw a line. + SkPoint point = CornerFromRect(cur_corner, view); + builder.lineTo(point); + } else { + // Draw the rounded corners for the larger view. + SkRect rect = SkRect::MakeWH(corner_radius_, corner_radius_); + MoveRectToCorner(cur_corner, view, rect); + AddRoundedCorner(cur_corner, rect, builder); + } + } + cur_corner = around.Next(); + } while (cur_corner != RoundedRectCutoutPathBuilder::Corner::kUpperLeft); + + // `close()` will draw a line from the last point to the start (top middle of + // the shape). + builder.close(); + return builder.detach(); +} + +} // namespace ash
diff --git a/ash/style/rounded_rect_cutout_path_builder.h b/ash/style/rounded_rect_cutout_path_builder.h new file mode 100644 index 0000000..a10597f5 --- /dev/null +++ b/ash/style/rounded_rect_cutout_path_builder.h
@@ -0,0 +1,74 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_STYLE_ROUNDED_RECT_CUTOUT_PATH_BUILDER_H_ +#define ASH_STYLE_ROUNDED_RECT_CUTOUT_PATH_BUILDER_H_ + +#include <optional> + +#include "ash/ash_export.h" +#include "base/containers/flat_map.h" +#include "third_party/skia/include/core/SkPath.h" +#include "ui/gfx/geometry/size_f.h" + +namespace ash { + +// Generates a clip path to render rounded corners and cutouts of arbitrary +// size and number (up to one cutout per corner). +// +// ______ +// | |__ < Cutout Upper Right +// | | +// | | +// |_______| +class ASH_EXPORT RoundedRectCutoutPathBuilder { + public: + // Possible corners that can have a cutout in counter-clockwise order. + enum class Corner { kUpperLeft, kLowerLeft, kLowerRight, kUpperRight }; + + // Constructs a builder where the desired clipping region size is `bounds`. + // Due to the default values of the corner radii, the minimum dimensions are + // 32 X 32 px. + RoundedRectCutoutPathBuilder(gfx::SizeF bounds); + RoundedRectCutoutPathBuilder(const RoundedRectCutoutPathBuilder&); + RoundedRectCutoutPathBuilder& operator=(const RoundedRectCutoutPathBuilder&); + ~RoundedRectCutoutPathBuilder(); + + // Sets the radius of the corners of the rectangle formed by bounds (not part + // of the cutout). + RoundedRectCutoutPathBuilder& CornerRadius(int radius); + + // Add a cutout at `corner` of `size`. Each `corner` may have a cutout. + // Setting a `corner` multiple times will replace that cutout. A `size` of + // zero will result in that cutout being removed. + RoundedRectCutoutPathBuilder& AddCutout(Corner corner, gfx::SizeF size); + + // Sets the radius of the interior corner of the cutout. + RoundedRectCutoutPathBuilder& CutoutInnerCornerRadius(int radius); + + // Sets the radius of the two exterior corners in the cutout. + RoundedRectCutoutPathBuilder& CutoutOuterCornerRadius(int radius); + + // Returns the configured path. May CHECK if the path cannot be drawn if the + // `bounds` or corner sizes are not sufficiently large for the configured + // radii. + SkPath Build(); + + private: + gfx::SizeF bounds_; + + // The radius of the corners without the cutout. + int corner_radius_ = 16; + + // Radii of the corners in the cutout. + int cutout_inner_corner_radius_ = 16; + int cutout_outer_corner_radius_ = 12; + + // Dimensions of each cutout. + base::flat_map<Corner, gfx::SizeF> cutouts_; +}; + +} // namespace ash + +#endif // ASH_STYLE_ROUNDED_RECT_CUTOUT_PATH_BUILDER_H_
diff --git a/ash/style/rounded_rect_cutout_path_builder_unittest.cc b/ash/style/rounded_rect_cutout_path_builder_unittest.cc new file mode 100644 index 0000000..c77cdb67f --- /dev/null +++ b/ash/style/rounded_rect_cutout_path_builder_unittest.cc
@@ -0,0 +1,99 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/rounded_rect_cutout_path_builder.h" + +#include <ostream> + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkPath.h" +#include "ui/gfx/geometry/size_f.h" + +// Pretty print SkRect for failure logs. +void PrintTo(const SkRect& size, std::ostream* os) { + *os << "(" << size.x() << ", " << size.y() << ") [" << size.width() << ", " + << size.height() << "]"; +} + +namespace ash { +namespace { + +constexpr gfx::SizeF kViewSize(114.f, 432.f); + +TEST(RoundedRectCutoutPathBuilderTest, RectanglePoints) { + RoundedRectCutoutPathBuilder builder(kViewSize); + builder.CornerRadius(0); + SkPath path = builder.Build(); + // A radius of 0 should be a rectangle so we have 4 points and the starting + // point. + EXPECT_EQ(path.countPoints(), 4 + 1); +} + +TEST(RoundedRectCutoutPathBuilderTest, RoundedCorners) { + RoundedRectCutoutPathBuilder builder(kViewSize); + builder.CornerRadius(16); + SkPath path = builder.Build(); + // A rounded rect has 12 points (3 for each ronded corner, one for the control + // point in conic and two for the start and end) and the starting + // point. + EXPECT_EQ(path.countPoints(), 12 + 1); +} + +TEST(RoundedRectCutoutPathBuilderTest, OneCutout) { + RoundedRectCutoutPathBuilder builder(kViewSize); + builder.AddCutout(RoundedRectCutoutPathBuilder::Corner::kLowerRight, + gfx::SizeF(30, 30)); + builder.CornerRadius(0); + SkPath path = builder.Build(); + + // Cutouts have 3 rounded corners each. Each rounded corner has 3 points (so 9 + // total). There are 3 other corners and the starting point. 13 total. + EXPECT_EQ(path.countPoints(), 9 + 3 + 1); +} + +TEST(RoundedRectCutoutPathBuilderTest, TwoCutouts) { + RoundedRectCutoutPathBuilder builder(kViewSize); + builder + .AddCutout(RoundedRectCutoutPathBuilder::Corner::kLowerRight, + gfx::SizeF(30, 30)) + .AddCutout(RoundedRectCutoutPathBuilder::Corner::kUpperRight, + gfx::SizeF(40, 20)) + .CornerRadius(0); + SkPath path = builder.Build(); + + // 2 cutouts, 2 normal corners, and the starting point. + EXPECT_EQ(path.countPoints(), 9 + 9 + 2 + 1); + + // Ensure the path is complete. + EXPECT_TRUE(path.isLastContourClosed()); + // The bounds should be equal to the View that the path will clip. + EXPECT_THAT( + path.getBounds(), + testing::Eq(SkRect::MakeSize({kViewSize.width(), kViewSize.height()}))); +} + +TEST(RoundedRectCutoutPathBuilderTest, RemoveCutout) { + RoundedRectCutoutPathBuilder builder(kViewSize); + builder.CornerRadius(0); + // Add cutout. + builder.AddCutout(RoundedRectCutoutPathBuilder::Corner::kUpperLeft, + gfx::SizeF(40, 40)); + // Remove the cutout. + builder.AddCutout(RoundedRectCutoutPathBuilder::Corner::kUpperLeft, + gfx::SizeF()); + + // The resulting path should be a rectangle. + SkPath path = builder.Build(); + EXPECT_EQ(path.countPoints(), 5); + + SkRect bounds; + EXPECT_TRUE(path.isRect(&bounds)); + EXPECT_THAT( + bounds, + testing::Eq(SkRect::MakeSize({kViewSize.width(), kViewSize.height()}))); +} + +} // namespace +} // namespace ash
diff --git a/ash/style/style_viewer/cutout_instances_grid_view_factory.cc b/ash/style/style_viewer/cutout_instances_grid_view_factory.cc new file mode 100644 index 0000000..8439221e --- /dev/null +++ b/ash/style/style_viewer/cutout_instances_grid_view_factory.cc
@@ -0,0 +1,183 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/style/rounded_rect_cutout_path_builder.h" +#include "ash/style/style_viewer/system_ui_components_grid_view.h" +#include "ash/style/style_viewer/system_ui_components_grid_view_factories.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/views/background.h" +#include "ui/views/view.h" + +namespace ash { + +namespace { + +constexpr size_t kGridViewRowNum = 4; +constexpr size_t kGridViewColNum = 4; +constexpr size_t kGridViewRowGroupSize = 1; +constexpr size_t kGridViewColGroupSize = 1; + +struct CutoutEntry { + std::u16string name; + SkColor color; + std::vector<RoundedRectCutoutPathBuilder::Corner> corners; + gfx::Size cutout_size; + std::optional<int> radius; + std::optional<int> outer_radius; + std::optional<int> inner_radius; +}; + +class CutoutsGridView : public SystemUIComponentsGridView { + public: + CutoutsGridView() + : SystemUIComponentsGridView(kGridViewRowNum, + kGridViewColNum, + kGridViewRowGroupSize, + kGridViewColGroupSize) {} + CutoutsGridView(const CutoutsGridView&) = delete; + CutoutsGridView& operator=(const CutoutsGridView&) = delete; + + ~CutoutsGridView() override = default; + + void AddCutoutSample(const CutoutEntry& entry) { + auto view = std::make_unique<views::View>(); + view->SetBackground(views::CreateSolidBackground(entry.color)); + view->SetPreferredSize(std::make_optional<gfx::Size>(200, 150)); + auto builder = + RoundedRectCutoutPathBuilder(gfx::SizeF(view->GetPreferredSize())); + if (!entry.corners.empty()) { + for (const auto& corner : entry.corners) { + builder.AddCutout(corner, gfx::SizeF(entry.cutout_size)); + } + } + if (entry.radius.has_value()) { + builder.CornerRadius(entry.radius.value()); + } + + if (entry.outer_radius.has_value()) { + builder.CutoutOuterCornerRadius(entry.outer_radius.value()); + } + + if (entry.inner_radius.has_value()) { + builder.CutoutInnerCornerRadius(entry.inner_radius.value()); + } + + view->SetClipPath(builder.Build()); + AddInstance(entry.name, std::move(view)); + } +}; + +} // namespace + +std::unique_ptr<SystemUIComponentsGridView> CreateCutoutsGridView() { + const std::array<CutoutEntry, kGridViewRowNum * kGridViewColNum> entries = {{ + // Row 1 + {u"TopLeft", + SK_ColorRED, + {RoundedRectCutoutPathBuilder::Corner::kUpperLeft}, + gfx::Size(40, 30)}, + {u"TopRight", + SK_ColorCYAN, + {RoundedRectCutoutPathBuilder::Corner::kUpperRight}, + gfx::Size(30, 50)}, + {u"BottomLeft", + SK_ColorGREEN, + {RoundedRectCutoutPathBuilder::Corner::kLowerLeft}, + gfx::Size(40, 40)}, + {u"BottomRight", + SK_ColorMAGENTA, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight}, + gfx::Size(30, 30)}, + // Row 2 + {u"TopLeft 4px corner", + SK_ColorRED, + {RoundedRectCutoutPathBuilder::Corner::kUpperLeft}, + gfx::Size(80, 30), + 4}, + {u"TopRight 8px corner", + SK_ColorCYAN, + {RoundedRectCutoutPathBuilder::Corner::kUpperRight}, + gfx::Size(30, 50), + 8}, + {u"BottomLeft 12px corner", + SK_ColorGREEN, + {RoundedRectCutoutPathBuilder::Corner::kLowerLeft}, + gfx::Size(40, 40), + 12}, + {u"BottomRight 20px corner", + SK_ColorMAGENTA, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight}, + gfx::Size(30, 30), + 20}, + // Row 3 + {u"No cutout", SK_ColorBLACK, {}, gfx::Size()}, + {u"4px corner. 6px small, 12px inner", + SK_ColorBLUE, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight}, + gfx::Size(40, 40), + 4, + 6, + 12}, + {u"60px corner, 12px small, 4px inner", + SK_ColorMAGENTA, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight}, + gfx::Size(60, 60), + 60, + 12, + 4}, + {u"Everything 6px", + SK_ColorRED, + {RoundedRectCutoutPathBuilder::Corner::kUpperRight}, + gfx::Size(20, 20), + 6, + 6, + 6}, + // Row 4 + {u"Lower Cutouts", + SK_ColorBLUE, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight, + RoundedRectCutoutPathBuilder::Corner::kLowerLeft}, + gfx::Size(40, 40), + 8, + 16, + 12}, + {u"Across", + SK_ColorMAGENTA, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight, + RoundedRectCutoutPathBuilder::Corner::kUpperLeft}, + gfx::Size(40, 40), + 8, + 16, + 12}, + {u"3 cutouts", + SK_ColorRED, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight, + RoundedRectCutoutPathBuilder::Corner::kLowerLeft, + RoundedRectCutoutPathBuilder::Corner::kUpperRight}, + gfx::Size(40, 40), + 8, + 16, + 12}, + {u"All 4 Cutouts", + SK_ColorGREEN, + {RoundedRectCutoutPathBuilder::Corner::kLowerRight, + RoundedRectCutoutPathBuilder::Corner::kLowerLeft, + RoundedRectCutoutPathBuilder::Corner::kUpperLeft, + RoundedRectCutoutPathBuilder::Corner::kUpperRight}, + gfx::Size(88, 60), + 16, + 12, + 20}, + }}; + + auto grid_view = std::make_unique<CutoutsGridView>(); + + for (const auto& entry : entries) { + grid_view->AddCutoutSample(entry); + } + + return grid_view; +} + +} // namespace ash
diff --git a/ash/style/style_viewer/system_ui_components_grid_view_factories.h b/ash/style/style_viewer/system_ui_components_grid_view_factories.h index 73e1da28..b228152 100644 --- a/ash/style/style_viewer/system_ui_components_grid_view_factories.h +++ b/ash/style/style_viewer/system_ui_components_grid_view_factories.h
@@ -29,6 +29,7 @@ std::unique_ptr<SystemUIComponentsGridView> CreatePaginationInstancesGridView(); std::unique_ptr<SystemUIComponentsGridView> CreateTypographyInstancesGridView(); std::unique_ptr<SystemUIComponentsGridView> CreateComboboxInstancesGridView(); +std::unique_ptr<SystemUIComponentsGridView> CreateCutoutsGridView(); } // namespace ash
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc index f6fc96c..86c6119 100644 --- a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc +++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
@@ -214,6 +214,8 @@ u"Combobox", base::BindRepeating(&CreateComboboxInstancesGridView)); viewer_view->AddComponent( u"Typography", base::BindRepeating(&CreateTypographyInstancesGridView)); + viewer_view->AddComponent(u"Cutouts", + base::BindRepeating(&CreateCutoutsGridView)); // Show PillButton on start. viewer_view->ShowComponentInstances(u"PillButton");
diff --git a/ash/system/audio/audio_detailed_view.cc b/ash/system/audio/audio_detailed_view.cc index 2f86d55..754456a 100644 --- a/ash/system/audio/audio_detailed_view.cc +++ b/ash/system/audio/audio_detailed_view.cc
@@ -901,7 +901,7 @@ audio_handler->SwitchToFrontOrRearMic(); } else { audio_handler->SwitchToDevice(device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); } }
diff --git a/ash/system/audio/audio_detailed_view_pixeltest.cc b/ash/system/audio/audio_detailed_view_pixeltest.cc index 7dca9de..838b03b 100644 --- a/ash/system/audio/audio_detailed_view_pixeltest.cc +++ b/ash/system/audio/audio_detailed_view_pixeltest.cc
@@ -47,9 +47,9 @@ AudioDevice output_device(FakeCrasAudioClient::Get()->node_list()[1]); AudioDevice input_device(FakeCrasAudioClient::Get()->node_list()[5]); audio_handler->SwitchToDevice(output_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); audio_handler->SwitchToDevice(input_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); UnifiedSystemTray* system_tray = GetPrimaryUnifiedSystemTray(); system_tray->ShowBubble(); @@ -84,7 +84,7 @@ client->SetNoiseCancellationSupported(true); audio_handler->RequestNoiseCancellationSupported(base::DoNothing()); audio_handler->SwitchToDevice(AudioDevice(internal_mic_node), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); UnifiedSystemTray* system_tray = GetPrimaryUnifiedSystemTray(); system_tray->ShowBubble();
diff --git a/ash/system/audio/audio_effects_controller_unittest.cc b/ash/system/audio/audio_effects_controller_unittest.cc index bad5225..85788630 100644 --- a/ash/system/audio/audio_effects_controller_unittest.cc +++ b/ash/system/audio/audio_effects_controller_unittest.cc
@@ -168,7 +168,7 @@ AudioDevice(GenerateAudioNode(noise_cancellation_supported ? kInternalSpeakerWithNC : kInternalSpeakerWithoutNC)), - /*notify=*/true, CrasAudioHandler::ACTIVATE_BY_USER); + /*notify=*/true, DeviceActivateType::kActivateByUser); } VideoConferenceTray* GetVideoConfereneTray() { @@ -371,7 +371,7 @@ // noise that cancellation is not-supported. cras_audio_handler()->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMicWithoutNC)), /*notify=*/true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_FALSE(audio_effects_controller()->IsEffectSupported( VcEffectId::kNoiseCancellation)); @@ -382,7 +382,7 @@ // that cancellation is supported. cras_audio_handler()->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMicWithNC)), /*notify=*/true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_TRUE(audio_effects_controller()->IsEffectSupported( VcEffectId::kNoiseCancellation)); @@ -393,7 +393,7 @@ // reports noise that cancellation is not-supported. cras_audio_handler()->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMicWithoutNC)), /*notify=*/true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_FALSE(audio_effects_controller()->IsEffectSupported( VcEffectId::kNoiseCancellation));
diff --git a/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc b/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc index d1b32f4..51f2bd58 100644 --- a/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc +++ b/ash/system/audio/unified_audio_detailed_view_controller_unittest.cc
@@ -312,16 +312,16 @@ auto jack_mic = AudioDevice(GenerateAudioNode(kMicJack)); cras_audio_handler_->SwitchToDevice(jack_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_FALSE(nbs_warning_view()); auto nbs_mic = AudioDevice(GenerateAudioNode(kNbsMic)); cras_audio_handler_->SwitchToDevice(nbs_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_TRUE(nbs_warning_view()); cras_audio_handler_->SwitchToDevice(jack_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_FALSE(nbs_warning_view()); } @@ -333,7 +333,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMic)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetPrimaryActiveInputNode()); EXPECT_TRUE(input_sliders_map_.find(kInternalMicId)->second->GetVisible()); @@ -341,7 +341,8 @@ EXPECT_TRUE(input_sliders_map_.find(kMicJackId)->second->GetVisible()); cras_audio_handler_->SwitchToDevice(AudioDevice(GenerateAudioNode(kMicJack)), - true, CrasAudioHandler::ACTIVATE_BY_USER); + true, + DeviceActivateType::kActivateByUser); EXPECT_EQ(kMicJackId, cras_audio_handler_->GetPrimaryActiveInputNode()); EXPECT_TRUE(input_sliders_map_.find(kMicJackId)->second->GetVisible()); @@ -357,7 +358,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalSpeaker)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(kInternalSpeakerId, cras_audio_handler_->GetPrimaryActiveOutputNode()); // Both sliders should be visible. @@ -367,7 +368,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kHeadphone)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(kHeadphoneId, cras_audio_handler_->GetPrimaryActiveOutputNode()); // Both sliders should be visible. EXPECT_TRUE(output_sliders_map_.find(kHeadphoneId)->second->GetVisible()); @@ -442,7 +443,8 @@ // Switches to `kMicJack` to make the internal mic inactive. cras_audio_handler_->SwitchToDevice(AudioDevice(GenerateAudioNode(kMicJack)), - true, CrasAudioHandler::ACTIVATE_BY_USER); + true, + DeviceActivateType::kActivateByUser); // Verifies the dual internal mic slider is inactive and its volume level // equals to the front mic's level. @@ -463,7 +465,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMic)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); std::unique_ptr<views::View> view = audio_detailed_view_controller_->CreateView(); @@ -479,7 +481,7 @@ auto internal_mic = AudioDevice(GenerateAudioNode(kInternalMic)); cras_audio_handler_->SwitchToDevice(internal_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // If `audio_detailed_view_` doesn't exist, this getter method will create the // view first. @@ -499,7 +501,7 @@ auto internal_mic = AudioDevice(GenerateAudioNode(kInternalMic)); cras_audio_handler_->SwitchToDevice(internal_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // If `audio_detailed_view_` doesn't exist, this getter method will create the // view first. @@ -530,7 +532,8 @@ cras_audio_handler_->RequestNoiseCancellationSupported(base::DoNothing()); cras_audio_handler_->SwitchToDevice(AudioDevice(GenerateAudioNode(kMicJack)), - true, CrasAudioHandler::ACTIVATE_BY_USER); + true, + DeviceActivateType::kActivateByUser); std::unique_ptr<views::View> view = audio_detailed_view_controller_->CreateView(); @@ -539,7 +542,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMic)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(1u, toggles_map_.size()); } @@ -552,7 +555,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMic)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // If `audio_detailed_view_` doesn't exist, this getter method will create the // view first. @@ -618,13 +621,13 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalMic)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); CheckSliderFocusBehavior(widget.get(), /*is_input_slider=*/true, kInternalMicId); cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalSpeaker)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); CheckSliderFocusBehavior(widget.get(), /*is_input_slider=*/false, kInternalSpeakerId); } @@ -638,7 +641,7 @@ cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kHeadphone)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(kHeadphoneId, cras_audio_handler_->GetPrimaryActiveOutputNode()); // Sets a volume level greater than 0 and the device is unmuted.
diff --git a/ash/system/focus_mode/focus_mode_chip_carousel.cc b/ash/system/focus_mode/focus_mode_chip_carousel.cc index a92a240..856c257 100644 --- a/ash/system/focus_mode/focus_mode_chip_carousel.cc +++ b/ash/system/focus_mode/focus_mode_chip_carousel.cc
@@ -156,8 +156,7 @@ UpdateGradient(); } -void FocusModeChipCarousel::SetTasks( - const std::vector<const api::Task*>& tasks) { +void FocusModeChipCarousel::SetTasks(const std::vector<FocusModeTask>& tasks) { scroll_contents_->RemoveAllChildViews(); if (tasks.empty()) { return; @@ -166,11 +165,10 @@ // Populate a maximum of `kMaxTasks` tasks. const size_t num_tasks = std::min(tasks.size(), kMaxTasks); for (size_t i = 0; i < num_tasks; i++) { - const api::Task* task = tasks[i]; views::LabelButton* chip = scroll_contents_->AddChildView(std::make_unique<views::LabelButton>( - base::BindRepeating(on_chip_pressed_, task), - base::UTF8ToUTF16(task->title))); + base::BindRepeating(on_chip_pressed_, tasks[i]), + base::UTF8ToUTF16(tasks[i].title))); SetupChip(chip, /*first=*/(i == 0)); }
diff --git a/ash/system/focus_mode/focus_mode_chip_carousel.h b/ash/system/focus_mode/focus_mode_chip_carousel.h index 6de3f55..15d10d7 100644 --- a/ash/system/focus_mode/focus_mode_chip_carousel.h +++ b/ash/system/focus_mode/focus_mode_chip_carousel.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_FOCUS_MODE_FOCUS_MODE_CHIP_CAROUSEL_H_ #include "ash/ash_export.h" +#include "ash/system/focus_mode/focus_mode_tasks_provider.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/layout/box_layout_view.h" @@ -17,10 +18,6 @@ namespace ash { -namespace api { -struct Task; -} // namespace api - // A horizontal scroll bar of chips for tasks. Selecting a task chip will save // it as the currently selected task for the focus session. class ASH_EXPORT FocusModeChipCarousel : public views::BoxLayoutView { @@ -28,7 +25,8 @@ public: // Called when a task chip is pressed, contains a task pointer that is alive // for the lifetime of the task chip. - using ChipPressedCallback = base::RepeatingCallback<void(const api::Task*)>; + using ChipPressedCallback = + base::RepeatingCallback<void(const FocusModeTask& task)>; explicit FocusModeChipCarousel(ChipPressedCallback on_chip_pressed); FocusModeChipCarousel(const FocusModeChipCarousel&) = delete; @@ -38,7 +36,7 @@ // TODO(b/305085993): Update setting logic once API is integrated. // Updates the carousel of task chips from the first 5 tasks in `tasks` and // scrolls the carousel back to the beginning. - void SetTasks(const std::vector<const api::Task*>& tasks); + void SetTasks(const std::vector<FocusModeTask>& tasks); // Returns whether the carousel is currently displaying any tasks. bool HasTasks() const;
diff --git a/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc b/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc index afa0329a1..9518d91 100644 --- a/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc +++ b/ash/system/focus_mode/focus_mode_chip_carousel_unittest.cc
@@ -4,8 +4,11 @@ #include "ash/system/focus_mode/focus_mode_chip_carousel.h" +#include <vector> + #include "ash/api/tasks/tasks_types.h" #include "ash/constants/ash_features.h" +#include "ash/system/focus_mode/focus_mode_tasks_provider.h" #include "ash/test/ash_test_base.h" #include "base/i18n/rtl.h" #include "base/test/scoped_feature_list.h" @@ -55,33 +58,21 @@ AshTestBase::TearDown(); } - std::unique_ptr<api::Task> MakeTask(const std::string& title) { - return std::make_unique<api::Task>( - /*id=*/base::NumberToString(task_id_++), title, - /*due=*/std::nullopt, /*completed=*/false, /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()); - } + std::vector<FocusModeTask> GetTasks(const std::vector<std::string>& titles) { + std::vector<FocusModeTask> tasks; - std::vector<std::unique_ptr<const api::Task>> MakeTasks( - const std::vector<std::string>& titles) { - std::vector<std::unique_ptr<const api::Task>> tasks; - for (const std::string& title : titles) { - tasks.push_back(MakeTask(title)); + base::Time updated = base::Time::Now(); + for (size_t i = 0; i != titles.size(); ++i) { + FocusModeTask& task = tasks.emplace_back(); + task.task_list_id = "task_list_id"; + task.task_id = base::NumberToString(i); + task.title = titles[i]; + task.updated = updated - base::Seconds(i); } + return tasks; } - std::vector<const api::Task*> GetTaskPtrs( - const std::vector<std::unique_ptr<const api::Task>>& tasks) { - std::vector<const api::Task*> task_ptrs; - for (const auto& task : tasks) { - task_ptrs.push_back(task.get()); - } - return task_ptrs; - } - FocusModeChipCarousel* focus_mode_chip_carousel() { return focus_mode_chip_carousel_; } @@ -106,8 +97,6 @@ base::test::ScopedFeatureList scoped_feature_; std::unique_ptr<views::Widget> widget_; raw_ptr<FocusModeChipCarousel> focus_mode_chip_carousel_; - // ID counter for creating fake tasks. - int task_id_ = 0; }; // Tests that the task list displays the list of tasks. @@ -116,9 +105,7 @@ auto validate_tasks = [&](const std::vector<std::string> task_titles) { SCOPED_TRACE(::testing::Message() << "Tasks length: " << task_titles.size()); - auto tasks = MakeTasks(task_titles); - focus_mode_chip_carousel()->SetTasks(GetTaskPtrs(tasks)); - + focus_mode_chip_carousel()->SetTasks(GetTasks(task_titles)); EXPECT_EQ(task_titles.size(), GetScrollContents()->GetChildrenInZOrder().size()); EXPECT_NE(task_titles.empty(), focus_mode_chip_carousel()->HasTasks()); @@ -141,14 +128,15 @@ // Tests that if more than 5 tasks are provided, the carousel only populates the // first 5. TEST_F(FocusModeChipCarouselTest, MaxOfFive) { - auto tasks = MakeTasks({"one", "two", "three", "four", "five", "six"}); - focus_mode_chip_carousel()->SetTasks(GetTaskPtrs(tasks)); + focus_mode_chip_carousel()->SetTasks( + GetTasks({"one", "two", "three", "four", "five", "six"})); EXPECT_EQ(5u, GetScrollContents()->GetChildrenInZOrder().size()); // The first 5 tasks should be populated. std::vector<LabelMatcherMatcherP<std::u16string>> task_labels = {}; - for (const std::string& task : {"one", "two", "three", "four", "five"}) { - task_labels.push_back(LabelMatcher(base::UTF8ToUTF16(task))); + for (const std::string& task_title : + {"one", "two", "three", "four", "five"}) { + task_labels.push_back(LabelMatcher(base::UTF8ToUTF16(task_title))); } EXPECT_THAT(GetScrollContents()->GetChildrenInZOrder(), testing::ElementsAreArray(task_labels)); @@ -162,14 +150,12 @@ // Setting 1 task shouldn't make the scroll view overflow, so there should // still be no gradient. - auto tasks_1 = MakeTasks({"Preparing for I485 form"}); - focus_mode_chip_carousel()->SetTasks(GetTaskPtrs(tasks_1)); + focus_mode_chip_carousel()->SetTasks(GetTasks({"Preparing for I485 form"})); views::test::RunScheduledLayout(focus_mode_chip_carousel()); EXPECT_FALSE(GetScrollView()->layer()->HasGradientMask()); // Three tasks should overflow the scroll view and the gradient should appear. - auto tasks_2 = MakeTasks(kTestTaskTitles); - focus_mode_chip_carousel()->SetTasks(GetTaskPtrs(tasks_2)); + focus_mode_chip_carousel()->SetTasks(GetTasks(kTestTaskTitles)); views::test::RunScheduledLayout(focus_mode_chip_carousel()); EXPECT_TRUE(GetScrollView()->layer()->HasGradientMask()); @@ -212,8 +198,7 @@ TEST_F(FocusModeChipCarouselTest, GradientInRTL) { base::i18n::SetRTLForTesting(true); - auto tasks = MakeTasks(kTestTaskTitles); - focus_mode_chip_carousel()->SetTasks(GetTaskPtrs(tasks)); + focus_mode_chip_carousel()->SetTasks(GetTasks(kTestTaskTitles)); views::test::RunScheduledLayout(focus_mode_chip_carousel()); EXPECT_TRUE(GetScrollView()->layer()->HasGradientMask());
diff --git a/ash/system/focus_mode/focus_mode_controller.cc b/ash/system/focus_mode/focus_mode_controller.cc index e423ed4..047c9c2c 100644 --- a/ash/system/focus_mode/focus_mode_controller.cc +++ b/ash/system/focus_mode/focus_mode_controller.cc
@@ -351,24 +351,20 @@ : current_session_->end_time(); } -void FocusModeController::SetSelectedTask(const api::Task* task) { - if (!task) { - selected_task_id_.clear(); - selected_task_title_.clear(); - } else { - selected_task_id_ = task->id; - selected_task_title_ = task->title; - } +void FocusModeController::SetSelectedTask(const FocusModeTask& task) { + selected_task_ = task; // TODO(b/305089077): Update user prefs. } bool FocusModeController::HasSelectedTask() const { - return !selected_task_id_.empty(); + return !selected_task_.task_id.empty(); } void FocusModeController::CompleteTask() { - tasks_provider_.MarkAsCompleted(selected_task_id_); - SetSelectedTask(nullptr); + tasks_provider_.UpdateTask(selected_task_.task_list_id, + selected_task_.task_id, selected_task_.title, + /*completed=*/true, base::DoNothing()); + SetSelectedTask({}); } void FocusModeController::MaybeShowEndingMomentNudge() {
diff --git a/ash/system/focus_mode/focus_mode_controller.h b/ash/system/focus_mode/focus_mode_controller.h index 672c409..4601905 100644 --- a/ash/system/focus_mode/focus_mode_controller.h +++ b/ash/system/focus_mode/focus_mode_controller.h
@@ -82,9 +82,12 @@ const std::optional<FocusModeSession>& current_session() const { return current_session_; } - const std::string& selected_task_id() const { return selected_task_id_; } + const std::string& selected_task_list_id() const { + return selected_task_.task_list_id; + } + const std::string& selected_task_id() const { return selected_task_.task_id; } const std::string& selected_task_title() const { - return selected_task_title_; + return selected_task_.title; } FocusModeTasksProvider& tasks_provider() { return tasks_provider_; } FocusModeSoundsController* focus_mode_sounds_controller() const { @@ -140,9 +143,8 @@ // ending moment needs to account for the extra duration). base::Time GetActualEndTime() const; - // Stores the `selected_task_id_` and `selected_task_title_` of the provided - // task. If task is `nullptr`, clears the selected task data. - void SetSelectedTask(const api::Task* task); + // Stores the provided `task`. + void SetSelectedTask(const FocusModeTask& task); // Returns whether there is a currently selected task. bool HasSelectedTask() const; @@ -207,10 +209,9 @@ // This is used to track the current session, if any. std::optional<FocusModeSession> current_session_; - // This is the selected task data, which can be populated from an existing - // task or created by the user. - std::string selected_task_id_; - std::string selected_task_title_; + // This is the selected task, which can be populated from an existing task or + // created by the user. + FocusModeTask selected_task_; // This is used to display focus mode playlists. Playback controls will be // added later.
diff --git a/ash/system/focus_mode/focus_mode_controller_unittest.cc b/ash/system/focus_mode/focus_mode_controller_unittest.cc index 67a63869..4f94533 100644 --- a/ash/system/focus_mode/focus_mode_controller_unittest.cc +++ b/ash/system/focus_mode/focus_mode_controller_unittest.cc
@@ -6,7 +6,10 @@ #include <memory> +#include "ash/api/tasks/fake_tasks_client.h" +#include "ash/api/tasks/tasks_controller.h" #include "ash/api/tasks/tasks_types.h" +#include "ash/api/tasks/test_tasks_delegate.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/ash_prefs.h" @@ -188,24 +191,23 @@ TEST_F(FocusModeControllerMultiUserTest, TasksFlow) { SimulateUserLogin(GetUser1AccountId()); + const std::string task_id = "0"; + const std::string title = "Focus Task"; + + FocusModeTask task; + task.task_list_id = "abc"; + task.task_id = task_id; + task.title = title; + task.updated = base::Time::Now(); + // Verify that initially there is no selected task. auto* controller = FocusModeController::Get(); EXPECT_FALSE(controller->HasSelectedTask()); // Select a task, and verify that the task data is accurate. - int id = 0; - const std::string title = "Focus Task"; - controller->SetSelectedTask(std::make_unique<api::Task>( - /*id=*/base::NumberToString(id), title, - /*due=*/std::nullopt, /*completed=*/false, - /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, - /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()) - .get()); + controller->SetSelectedTask(task); EXPECT_TRUE(controller->HasSelectedTask()); - EXPECT_EQ(base::NumberToString(id), controller->selected_task_id()); + EXPECT_EQ(task_id, controller->selected_task_id()); EXPECT_EQ(title, controller->selected_task_title()); // Complete the task, and verify that the task data is cleared.
diff --git a/ash/system/focus_mode/focus_mode_detailed_view_unittest.cc b/ash/system/focus_mode/focus_mode_detailed_view_unittest.cc index 18d89c2a..ae4114f7d 100644 --- a/ash/system/focus_mode/focus_mode_detailed_view_unittest.cc +++ b/ash/system/focus_mode/focus_mode_detailed_view_unittest.cc
@@ -799,17 +799,13 @@ EXPECT_FALSE(controller->in_focus_session()); // 2. Start a focus session with a selected task. - int id = 0; - const std::string title = "Focus Task"; - controller->SetSelectedTask(std::make_unique<api::Task>( - /*id=*/base::NumberToString(id), title, - /*due=*/std::nullopt, /*completed=*/false, - /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, - /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()) - .get()); + FocusModeTask task; + task.task_list_id = "abc"; + task.task_id = "1"; + task.title = "Focus Task"; + task.updated = base::Time::Now(); + + controller->SetSelectedTask(task); EXPECT_TRUE(controller->HasSelectedTask()); controller->ToggleFocusMode();
diff --git a/ash/system/focus_mode/focus_mode_task_view.cc b/ash/system/focus_mode/focus_mode_task_view.cc index 0504b30c..2eeb0c1 100644 --- a/ash/system/focus_mode/focus_mode_task_view.cc +++ b/ash/system/focus_mode/focus_mode_task_view.cc
@@ -274,7 +274,7 @@ if (has_selected_task) { task_title_ = base::UTF8ToUTF16(controller->selected_task_title()); } else { - chip_carousel_->SetTasks(controller->tasks_provider().GetTaskList()); + chip_carousel_->SetTasks(controller->tasks_provider().GetSortedTaskList()); } UpdateStyle(/*show_selected_state=*/has_selected_task); @@ -293,8 +293,9 @@ auto* controller = FocusModeController::Get(); if (controller->HasSelectedTask()) { - controller->tasks_provider().UpdateTaskTitle( - controller->selected_task_id(), base::UTF16ToUTF8(task_title), + controller->tasks_provider().UpdateTask( + controller->selected_task_list_id(), controller->selected_task_id(), + base::UTF16ToUTF8(task_title), /*completed=*/false, base::BindOnce(&FocusModeTaskView::OnTaskSelected, weak_factory_.GetWeakPtr())); } else { @@ -305,15 +306,15 @@ } } -void FocusModeTaskView::OnTaskSelected(const api::Task* task) { - if (!task) { +void FocusModeTaskView::OnTaskSelected(const FocusModeTask& task_entry) { + if (task_entry.task_id.empty()) { OnClearTask(); return; } - task_title_ = base::UTF8ToUTF16(task->title); + task_title_ = base::UTF8ToUTF16(task_entry.title); textfield_->SetText(task_title_); - FocusModeController::Get()->SetSelectedTask(task); + FocusModeController::Get()->SetSelectedTask(task_entry); UpdateStyle(/*show_selected_state=*/true); } @@ -321,12 +322,12 @@ task_title_.clear(); textfield_->SetText(std::u16string()); auto* controller = FocusModeController::Get(); - controller->SetSelectedTask(nullptr); + controller->SetSelectedTask({}); // Only update `chip_carousel_` when it's invisible to avoid the crash when // moving focus to it by tabbing from an empty text of `textfield_` to the // `chip_carousel_`. if (!chip_carousel_->GetVisible()) { - chip_carousel_->SetTasks(controller->tasks_provider().GetTaskList()); + chip_carousel_->SetTasks(controller->tasks_provider().GetSortedTaskList()); } UpdateStyle(/*show_selected_state=*/false); }
diff --git a/ash/system/focus_mode/focus_mode_task_view.h b/ash/system/focus_mode/focus_mode_task_view.h index f10baca8..b8d2dd1 100644 --- a/ash/system/focus_mode/focus_mode_task_view.h +++ b/ash/system/focus_mode/focus_mode_task_view.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_FOCUS_MODE_FOCUS_MODE_TASK_VIEW_H_ #include "ash/ash_export.h" +#include "ash/system/focus_mode/focus_mode_tasks_provider.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/layout/box_layout_view.h" @@ -15,10 +16,6 @@ namespace ash { -namespace api { -struct Task; -} // namespace api - class FocusModeChipCarousel; // The class will be used in the `FocusModeDetailedView` under the task view @@ -40,7 +37,7 @@ // Updates `task_title_` and saves the task information to the focus mode // controller. - void OnTaskSelected(const api::Task* task); + void OnTaskSelected(const FocusModeTask& task_entry); // Clears the stored task data, and fetches an updated task list to display in // the carousel.
diff --git a/ash/system/focus_mode/focus_mode_tasks_provider.cc b/ash/system/focus_mode/focus_mode_tasks_provider.cc index 4e4ea77..6ebce05 100644 --- a/ash/system/focus_mode/focus_mode_tasks_provider.cc +++ b/ash/system/focus_mode/focus_mode_tasks_provider.cc
@@ -8,6 +8,7 @@ #include <vector> #include "ash/api/tasks/tasks_types.h" +#include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" @@ -79,25 +80,63 @@ .due_string = "", .updated_string = "10 Nov 2023 0:00 GMT"}}; -std::unique_ptr<api::Task> GetTaskFromDummyTask( - const DummyTaskData& task_data) { - base::Time update_date; +FocusModeTask GetTaskFromDummyTask(const DummyTaskData& task_data) { + FocusModeTask task; + + base::Time update_date, due_date; CHECK(base::Time::FromString(task_data.updated_string, &update_date)); - base::Time due_date; - return std::make_unique<api::Task>( - task_data.id, task_data.title, - base::Time::FromString(task_data.due_string, &due_date) - ? std::make_optional<base::Time>(due_date) - : std::nullopt, - task_data.completed, - /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, update_date, /*web_view_link=*/GURL()); + task.task_id = task_data.id; + task.task_list_id = "1"; + task.due = base::Time::FromString(task_data.due_string, &due_date) + ? std::make_optional<base::Time>(due_date) + : std::nullopt; + task.updated = update_date; + task.title = task_data.title; + + return task; } +// Used to sort tasks for the carousel. +struct TaskComparator { + enum class TaskGroupOrdering { + kPastDue, + kDueSoon, + kDueLater, + }; + + bool operator()(const FocusModeTask& lhs, const FocusModeTask& rhs) const { + auto lhs_group = GetOrdering(lhs); + auto rhs_group = GetOrdering(rhs); + if (lhs_group != rhs_group) { + return lhs_group < rhs_group; + } + + return lhs.updated > rhs.updated; + } + + TaskGroupOrdering GetOrdering(const FocusModeTask& entry) const { + auto remaining = entry.due.value_or(base::Time::Max()) - now; + if (remaining < base::Hours(0)) { + return TaskGroupOrdering::kPastDue; + } else if (remaining < base::Hours(24)) { + return TaskGroupOrdering::kDueSoon; + } + return TaskGroupOrdering::kDueLater; + } + + base::Time now; +}; + } // namespace +FocusModeTask::FocusModeTask() = default; +FocusModeTask::~FocusModeTask() = default; +FocusModeTask::FocusModeTask(const FocusModeTask&) = default; +FocusModeTask::FocusModeTask(FocusModeTask&&) = default; +FocusModeTask& FocusModeTask::operator=(const FocusModeTask&) = default; +FocusModeTask& FocusModeTask::operator=(FocusModeTask&&) = default; + FocusModeTasksProvider::FocusModeTasksProvider() { for (const DummyTaskData& task_data : kTaskInitializationData) { InsertTask(GetTaskFromDummyTask(task_data)); @@ -106,61 +145,48 @@ FocusModeTasksProvider::~FocusModeTasksProvider() = default; -std::vector<const api::Task*> FocusModeTasksProvider::GetTaskList() const { - std::vector<const api::Task*> tasks; - tasks.reserve(tasks_data_.size()); - - for (const std::unique_ptr<api::Task>& task : tasks_data_) { - tasks.push_back(task.get()); - } - - return tasks; +std::vector<FocusModeTask> FocusModeTasksProvider::GetSortedTaskList() const { + return sorted_tasks_; } void FocusModeTasksProvider::AddTask(const std::string& title, OnTaskSavedCallback callback) { - std::unique_ptr<api::Task> task = std::make_unique<api::Task>( - /*id=*/base::NumberToString(task_id_++), title, - /*due=*/std::nullopt, /*completed=*/false, /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()); + FocusModeTask task; + task.task_list_id = "1"; + task.task_id = base::NumberToString(task_id_++); + task.title = title; + task.updated = base::Time::Now(); - api::Task* task_ptr = task.get(); - InsertTask(std::move(task)); - std::move(callback).Run(task_ptr); + InsertTask(task); + std::move(callback).Run(task); } -void FocusModeTasksProvider::UpdateTaskTitle(const std::string& task_id, - const std::string& title, - OnTaskSavedCallback callback) { - api::Task* found_task = nullptr; - for (auto& task : tasks_data_) { - if (task_id == task->id) { - task->title = title; - found_task = task.get(); - break; - } - } - std::move(callback).Run(found_task); -} +void FocusModeTasksProvider::UpdateTask(const std::string& task_list_id, + const std::string& task_id, + const std::string& title, + bool completed, + OnTaskSavedCallback callback) { + auto task = base::ranges::find_if(sorted_tasks_, [&](const auto& task) { + return task.task_id == task_id && task.task_list_id == task_list_id; + }); -void FocusModeTasksProvider::MarkAsCompleted(const std::string& task_id) { - std::erase_if(tasks_data_, - [task_id](const auto& task) { return task->id == task_id; }); -} - -void FocusModeTasksProvider::InsertTask(std::unique_ptr<api::Task> task) { - for (auto it = tasks_data_.begin(); it != tasks_data_.end(); it++) { - if ((task->due.value_or(base::Time::Max()) < - it->get()->due.value_or(base::Time::Max())) || - (!it->get()->due.has_value() && task->updated > it->get()->updated)) { - tasks_data_.insert(it, std::move(task)); - return; - } + if (task == sorted_tasks_.end()) { + std::move(callback).Run(FocusModeTask{}); + return; } - tasks_data_.push_back(std::move(task)); + task->title = title; + + auto copy = *task; + if (completed) { + sorted_tasks_.erase(task); + } + std::move(callback).Run(copy); +} + +void FocusModeTasksProvider::InsertTask(FocusModeTask task) { + sorted_tasks_.push_back(std::move(task)); + base::ranges::sort(sorted_tasks_, TaskComparator{base::Time::Now()}); } } // namespace ash
diff --git a/ash/system/focus_mode/focus_mode_tasks_provider.h b/ash/system/focus_mode/focus_mode_tasks_provider.h index 301c1a2..3ccc374 100644 --- a/ash/system/focus_mode/focus_mode_tasks_provider.h +++ b/ash/system/focus_mode/focus_mode_tasks_provider.h
@@ -10,54 +10,80 @@ #include "ash/ash_export.h" #include "base/functional/callback_forward.h" +#include "base/time/time.h" namespace ash { -namespace api { -struct Task; -} // namespace api +// Represents a task. +struct ASH_EXPORT FocusModeTask { + FocusModeTask(); + ~FocusModeTask(); + FocusModeTask(const FocusModeTask&); + FocusModeTask(FocusModeTask&&); + FocusModeTask& operator=(const FocusModeTask&); + FocusModeTask& operator=(FocusModeTask&&); + + std::string task_list_id; + std::string task_id; + std::string title; + + // The time when this task was last updated. + base::Time updated; + + // Optional due time for the task. + std::optional<base::Time> due; +}; // A specialized interface that Focus Mode can use to fetch a filtered list of // tasks to display. Currently only provides dummy data. class ASH_EXPORT FocusModeTasksProvider { public: // Done callback for `AddTask` and `UpdateTaskTitle`. If the request completes - // successfully, `task` points to the newly created or updated task, or - // `nullptr` otherwise. - using OnTaskSavedCallback = base::OnceCallback<void(const api::Task* task)>; + // successfully, `task_entry` points to the newly created or updated + // `FocusModeTask`, or an empty `FocusModeTask` with nullptr members + // otherwise. + using OnTaskSavedCallback = + base::OnceCallback<void(const FocusModeTask& task_entry)>; FocusModeTasksProvider(); FocusModeTasksProvider(const FocusModeTasksProvider&) = delete; FocusModeTasksProvider& operator=(const FocusModeTasksProvider&) = delete; ~FocusModeTasksProvider(); - // Provides a filtered list of tasks that can be displayed in Focus Mode. - // Tasks are prioritized by earliest due date, then by the timestamp of their - // last update. - std::vector<const api::Task*> GetTaskList() const; + // Provides a sorted list of `FocusModeTask` instances that can be displayed + // in Focus Mode. + std::vector<FocusModeTask> GetSortedTaskList() const; - // Creates a new task with name `title` and adds it to `tasks_data_`. + // Creates a new task with name `title` and adds it to `task_list_`. Returns + // the added `FocusModeTask` in `callback`, or an empty `FocusModeTask` if an + // error has occurred. void AddTask(const std::string& title, OnTaskSavedCallback callback); - // Finds the task by `task_id` and updates the task title. Returns a nullptr - // if the task cannot be found. - void UpdateTaskTitle(const std::string& task_id, - const std::string& title, - OnTaskSavedCallback callback); - - // Removes the task with `task_id` from `tasks_data_`. - void MarkAsCompleted(const std::string& task_id); + // Finds the task by `task_list_id` and `task_id` and updates the task title + // and completion status. Returns a `FocusModeTask` in `callback`, or an empty + // `FocusModeTask` if the task could not be found or an error has occurred. + void UpdateTask(const std::string& task_list_id, + const std::string& task_id, + const std::string& title, + bool completed, + OnTaskSavedCallback callback); private: - // Helper function for inserting tasks into `tasks_data_`. - void InsertTask(std::unique_ptr<api::Task> task); + // Helper function for inserting `FocusModeTask` instances into + // `sorted_tasks_`. + void InsertTask(FocusModeTask task); // ID counter for creating tasks. Start from above where IDs in // `kTaskInitializationData` end to avoid conflicts. // TODO(b/306271332): Create a new task. int task_id_ = 10; - // Tasks for the loaded list. - std::vector<std::unique_ptr<api::Task>> tasks_data_; + + // Entries here are sorted in the following priority order: + // 1. Entries containing `Task`s which are past due. + // 2. Entries containing `Task`s which are due in the next 24 hours. + // 3. All other entries. + // Entries within each group are sorted by their `Task`'s update date. + std::vector<FocusModeTask> sorted_tasks_; }; } // namespace ash
diff --git a/ash/system/focus_mode/focus_mode_tray_unittest.cc b/ash/system/focus_mode/focus_mode_tray_unittest.cc index 755848c..ea55cf7 100644 --- a/ash/system/focus_mode/focus_mode_tray_unittest.cc +++ b/ash/system/focus_mode/focus_mode_tray_unittest.cc
@@ -5,7 +5,10 @@ #include "ash/system/focus_mode/focus_mode_tray.h" #include "ash/accessibility/accessibility_controller.h" +#include "ash/api/tasks/fake_tasks_client.h" +#include "ash/api/tasks/tasks_controller.h" #include "ash/api/tasks/tasks_types.h" +#include "ash/api/tasks/test_tasks_delegate.h" #include "ash/constants/ash_features.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" @@ -186,16 +189,14 @@ ui::ScopedAnimationDurationScaleMode duration( ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + FocusModeTask task; + task.task_list_id = "123"; + task.task_id = "1"; + task.title = "make a travel plan"; + task.updated = base::Time::Now(); + FocusModeController* controller = FocusModeController::Get(); - controller->SetSelectedTask( - std::make_unique<api::Task>( - /*id=*/base::NumberToString(0), "make a travel plan", - /*due=*/std::nullopt, /*completed=*/false, /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, - /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()) - .get()); + controller->SetSelectedTask(task); // Start focus mode and click the tray to activate the button. controller->ToggleFocusMode(); @@ -296,15 +297,14 @@ const std::u16string time_remaining = focus_mode_util::GetDurationString( session_duration, /*digital_format=*/false); controller->SetInactiveSessionDuration(session_duration); - controller->SetSelectedTask(std::make_unique<api::Task>( - /*id=*/base::NumberToString(1), task_name, - /*due=*/std::nullopt, /*completed=*/false, - /*has_subtasks=*/false, - /*has_email_link=*/false, - /*has_notes=*/false, - /*updated=*/base::Time::Now(), - /*web_view_link=*/GURL()) - .get()); + + FocusModeTask task; + task.task_list_id = "abc"; + task.task_id = "1"; + task.title = task_name; + task.updated = base::Time::Now(); + + controller->SetSelectedTask(task); controller->ToggleFocusMode(); LeftClickOn(focus_mode_tray_);
diff --git a/ash/system/notification_center/views/pinned_notification_view.cc b/ash/system/notification_center/views/pinned_notification_view.cc index 55cc8cc..31cd605 100644 --- a/ash/system/notification_center/views/pinned_notification_view.cc +++ b/ash/system/notification_center/views/pinned_notification_view.cc
@@ -181,35 +181,6 @@ bool has_icon_button = !has_pill_button && !notification.buttons().empty() && !notification.buttons()[0].vector_icon->is_empty(); - if (!notification.shortcut_text().empty()) { - buttons_container->AddChildView( - views::Builder<views::Label>() - .SetID(VIEW_ID_PINNED_NOTIFICATION_SHORTCUT_LABEL) - .SetText(notification.shortcut_text()) - .SetTooltipText(notification.shortcut_text()) - .SetEnabledColorId(cros_tokens::kCrosSysOnSurfaceVariant) - .SetAutoColorReadabilityEnabled(false) - .SetSubpixelRenderingEnabled(false) - .SetFontList(TypographyProvider::Get()->ResolveTypographyToken( - TypographyToken::kCrosAnnotation1)) - .Build()); - - // A divider dot will only be added if there are still elements to the right - // of the shortcut text. - if (has_pill_button || has_icon_button) { - buttons_container->AddChildView( - views::Builder<views::Label>() - .SetID(VIEW_ID_PINNED_NOTIFICATION_SHORTCUT_DIVIDER_LABEL) - .SetText(kNotificationTitleRowDivider) - .SetEnabledColorId(cros_tokens::kCrosSysOnSurfaceVariant) - .SetAutoColorReadabilityEnabled(false) - .SetSubpixelRenderingEnabled(false) - .SetFontList(TypographyProvider::Get()->ResolveTypographyToken( - TypographyToken::kCrosAnnotation1)) - .Build()); - } - } - if (has_pill_button) { const std::u16string& pill_button_title = notification.buttons()[0].title; @@ -295,7 +266,7 @@ MessageView::UpdateWithNotification(notification); // Only the `title` and `subtitle` labels can be updated. Any other changes - // made to the buttons, icon or shortcut text will be ignored. + // made to the buttons or icon will be ignored. auto* title_label = GetTitleLabel(this); if (title_label && title_label->GetText() != notification.title()) { auto catalog_name = GetCatalogName(notification);
diff --git a/ash/system/notification_center/views/pinned_notification_view.h b/ash/system/notification_center/views/pinned_notification_view.h index 15c810a..2523bea 100644 --- a/ash/system/notification_center/views/pinned_notification_view.h +++ b/ash/system/notification_center/views/pinned_notification_view.h
@@ -18,8 +18,8 @@ // Ash Pinned Notification View to be used when the `Ongoing Processes` flag is // enabled (go/ongoing-processes-spec). This view must have a title and an icon, -// and optionally supports a subtitle, a shortcut hint, and a pill button or up -// to two icon buttons. +// and optionally supports a subtitle, and a pill button or up to two icon +// buttons. class ASH_EXPORT PinnedNotificationView : public message_center::MessageView { METADATA_HEADER(PinnedNotificationView, message_center::MessageView)
diff --git a/ash/system/notification_center/views/pinned_notification_view_unittest.cc b/ash/system/notification_center/views/pinned_notification_view_unittest.cc index b399a53c..d0173cd 100644 --- a/ash/system/notification_center/views/pinned_notification_view_unittest.cc +++ b/ash/system/notification_center/views/pinned_notification_view_unittest.cc
@@ -37,16 +37,6 @@ VIEW_ID_PINNED_NOTIFICATION_SUBTITLE_LABEL)); } -views::Label* GetShortcutLabel(views::View* notification_view) { - return views::AsViewClass<views::Label>(notification_view->GetViewByID( - VIEW_ID_PINNED_NOTIFICATION_SHORTCUT_LABEL)); -} - -views::Label* GetShortcutDividerLabel(views::View* notification_view) { - return views::AsViewClass<views::Label>(notification_view->GetViewByID( - VIEW_ID_PINNED_NOTIFICATION_SHORTCUT_DIVIDER_LABEL)); -} - PillButton* GetPillButton(views::View* notification_view) { return views::AsViewClass<PillButton>( notification_view->GetViewByID(VIEW_ID_PINNED_NOTIFICATION_PILL_BUTTON)); @@ -101,8 +91,6 @@ EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); ASSERT_TRUE(GetSubtitleLabel(pinned_notification_view)); EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); EXPECT_FALSE(GetPillButton(pinned_notification_view)); EXPECT_FALSE(GetPrimaryIconButton(pinned_notification_view)); EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); @@ -131,39 +119,6 @@ EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); ASSERT_TRUE(GetSubtitleLabel(pinned_notification_view)); EXPECT_TRUE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); - EXPECT_FALSE(GetPillButton(pinned_notification_view)); - EXPECT_FALSE(GetPrimaryIconButton(pinned_notification_view)); - EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); -} - -// Tests that the mandatory fields and a shortcut text label are created. -TEST_F(PinnedNotificationViewTest, ShortcutText) { - std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget(); - - message_center::RichNotificationData data; - data.shortcut_text = sample_text; - - auto notification = - ash::SystemNotificationBuilder() - .SetId("id") - .SetCatalogName(NotificationCatalogName::kTestCatalogName) - .SetSmallImage(*sample_icon) - .SetTitle(sample_text) - .SetOptionalFields(data) - .Build( - /*keep_timestamp=*/false); - - PinnedNotificationView* pinned_notification_view = widget->SetContentsView( - std::make_unique<PinnedNotificationView>(notification)); - - // Test that appropriate notification elements were created. - EXPECT_TRUE(GetIcon(pinned_notification_view)); - EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_TRUE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); EXPECT_FALSE(GetPillButton(pinned_notification_view)); EXPECT_FALSE(GetPrimaryIconButton(pinned_notification_view)); EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); @@ -193,41 +148,6 @@ EXPECT_TRUE(GetIcon(pinned_notification_view)); EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); - EXPECT_TRUE(GetPillButton(pinned_notification_view)); - EXPECT_FALSE(GetPrimaryIconButton(pinned_notification_view)); - EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); -} - -// Tests that the mandatory fields and a shortcut text + a pill button are -// created. A shortcut divider should also be created. -TEST_F(PinnedNotificationViewTest, ShortcutTextAndPillButton) { - std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget(); - - message_center::RichNotificationData data; - data.shortcut_text = sample_text; - data.buttons.emplace_back(message_center::ButtonInfo(/*title=*/sample_text)); - - auto notification = - ash::SystemNotificationBuilder() - .SetId("id") - .SetCatalogName(NotificationCatalogName::kTestCatalogName) - .SetSmallImage(*sample_icon) - .SetTitle(sample_text) - .SetOptionalFields(data) - .Build( - /*keep_timestamp=*/false); - - PinnedNotificationView* pinned_notification_view = widget->SetContentsView( - std::make_unique<PinnedNotificationView>(notification)); - - // Test that appropriate notification elements were created. - EXPECT_TRUE(GetIcon(pinned_notification_view)); - EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_TRUE(GetShortcutLabel(pinned_notification_view)); - EXPECT_TRUE(GetShortcutDividerLabel(pinned_notification_view)); EXPECT_TRUE(GetPillButton(pinned_notification_view)); EXPECT_FALSE(GetPrimaryIconButton(pinned_notification_view)); EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); @@ -258,8 +178,6 @@ EXPECT_TRUE(GetIcon(pinned_notification_view)); EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); EXPECT_FALSE(GetPillButton(pinned_notification_view)); EXPECT_TRUE(GetPrimaryIconButton(pinned_notification_view)); EXPECT_FALSE(GetSecondaryIconButton(pinned_notification_view)); @@ -292,44 +210,6 @@ EXPECT_TRUE(GetIcon(pinned_notification_view)); EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetShortcutLabel(pinned_notification_view)); - EXPECT_FALSE(GetShortcutDividerLabel(pinned_notification_view)); - EXPECT_FALSE(GetPillButton(pinned_notification_view)); - EXPECT_TRUE(GetPrimaryIconButton(pinned_notification_view)); - EXPECT_TRUE(GetSecondaryIconButton(pinned_notification_view)); -} - -// Tests that the mandatory fields and a shortcut text + two icon buttons are -// created. A shortcut divider should also be created. -TEST_F(PinnedNotificationViewTest, ShortcutTextAndIconButtons) { - std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget(); - - message_center::RichNotificationData data; - data.shortcut_text = sample_text; - data.buttons.emplace_back(message_center::ButtonInfo( - /*vector_icon=*/sample_icon, /*accessible_name=*/sample_text)); - data.buttons.emplace_back(message_center::ButtonInfo( - /*vector_icon=*/sample_icon, /*accessible_name=*/sample_text)); - - auto notification = - ash::SystemNotificationBuilder() - .SetId("id") - .SetCatalogName(NotificationCatalogName::kTestCatalogName) - .SetSmallImage(*sample_icon) - .SetTitle(sample_text) - .SetOptionalFields(data) - .Build( - /*keep_timestamp=*/false); - - PinnedNotificationView* pinned_notification_view = widget->SetContentsView( - std::make_unique<PinnedNotificationView>(notification)); - - // Test that appropriate notification elements were created. - EXPECT_TRUE(GetIcon(pinned_notification_view)); - EXPECT_TRUE(GetTitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_FALSE(GetSubtitleLabel(pinned_notification_view)->GetVisible()); - EXPECT_TRUE(GetShortcutLabel(pinned_notification_view)); - EXPECT_TRUE(GetShortcutDividerLabel(pinned_notification_view)); EXPECT_FALSE(GetPillButton(pinned_notification_view)); EXPECT_TRUE(GetPrimaryIconButton(pinned_notification_view)); EXPECT_TRUE(GetSecondaryIconButton(pinned_notification_view));
diff --git a/ash/system/toast/system_toast_view.cc b/ash/system/toast/system_toast_view.cc index f83fa64a..3de562a 100644 --- a/ash/system/toast/system_toast_view.cc +++ b/ash/system/toast/system_toast_view.cc
@@ -11,6 +11,7 @@ #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/cpp/style/color_provider.h" #include "ash/public/cpp/system/toast_data.h" +#include "ash/shell.h" #include "ash/style/ash_color_id.h" #include "ash/style/pill_button.h" #include "ash/style/system_shadow.h" @@ -41,10 +42,13 @@ constexpr int kToastLabelMaxWidth = 512; constexpr int kToastLeadingIconSize = 20; constexpr int kToastLeadingIconPaddingWidth = 14; +constexpr int kDismissButtonFocusRingHaloInset = 1; } // namespace -SystemToastView::SystemToastView(const ToastData& toast_data) { +SystemToastView::SystemToastView(const ToastData& toast_data) + : scoped_a11y_overrider_( + std::make_unique<ScopedA11yOverrideWindowSetter>()) { // Paint to layer so the background can be transparent. SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -88,13 +92,27 @@ if (has_button) { AddChildView( views::Builder<PillButton>() + .CopyAddressTo(&dismiss_button_) .SetID(VIEW_ID_TOAST_BUTTON) .SetCallback(std::move(toast_data.dismiss_callback)) .SetText(toast_data.dismiss_text) .SetTooltipText(toast_data.dismiss_text) .SetPillButtonType(PillButton::Type::kAccentFloatingWithoutIcon) - .SetFocusBehavior(views::View::FocusBehavior::ACCESSIBLE_ONLY) + .SetFocusBehavior(views::View::FocusBehavior::ALWAYS) .Build()); + + // The button's focus ring predicate is overridden since it's not directly + // focus accessible by tab traversal. The `is_dismiss_button_highlighted_` + // member variable is set through `ToggleButtonA11yFocus`. + auto* button_focus_ring = views::FocusRing::Get(dismiss_button_); + button_focus_ring->SetHaloInset(kDismissButtonFocusRingHaloInset); + button_focus_ring->SetOutsetFocusRingDisabled(true); + button_focus_ring->SetHasFocusPredicate(base::BindRepeating( + [](const SystemToastView* toast_view, const views::View* view) { + return toast_view->is_dismiss_button_highlighted_; + }, + base::Unretained(this))); + button_focus_ring->SetVisible(false); } label->SetMaximumWidth(kToastLabelMaxWidth); @@ -120,6 +138,25 @@ SystemToastView::~SystemToastView() = default; +void SystemToastView::ToggleButtonA11yFocus() { + if (!dismiss_button_) { + return; + } + + // `is_dismiss_button_highlighted_` indicates the desired focus state. + is_dismiss_button_highlighted_ = !is_dismiss_button_highlighted_; + if (is_dismiss_button_highlighted_) { + scoped_a11y_overrider_->MaybeUpdateA11yOverrideWindow( + dismiss_button_->GetWidget()->GetNativeWindow()); + dismiss_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, + true); + } + + auto* button_focus_ring = views::FocusRing::Get(dismiss_button_); + button_focus_ring->SetVisible(is_dismiss_button_highlighted_); + button_focus_ring->SchedulePaint(); +} + void SystemToastView::AddedToWidget() { shadow_->ObserveColorProviderSource(GetWidget());
diff --git a/ash/system/toast/system_toast_view.h b/ash/system/toast/system_toast_view.h index 412c8ec..6fa3ace 100644 --- a/ash/system/toast/system_toast_view.h +++ b/ash/system/toast/system_toast_view.h
@@ -10,9 +10,14 @@ #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/layout/flex_layout_view.h" +namespace views { +class LabelButton; +} // namespace views + namespace ash { struct ToastData; +class ScopedA11yOverrideWindowSetter; class SystemShadow; // The System Toast view. (go/toast-style-spec) @@ -28,12 +33,32 @@ SystemToastView& operator=(const SystemToastView&) = delete; ~SystemToastView() override; + bool is_dismiss_button_highlighted() const { + return is_dismiss_button_highlighted_; + } + + views::LabelButton* dismiss_button() const { return dismiss_button_; } + + // Toggles the dismiss button's focus. This function is necessary since toasts + // are not directly focus accessible by tab traversal. + void ToggleButtonA11yFocus(); + private: + // Owned by the views hierarchy. + raw_ptr<views::LabelButton> dismiss_button_ = nullptr; std::unique_ptr<SystemShadow> shadow_; // views::View: void AddedToWidget() override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + + // Used to a11y focus and draw a focus ring on the dismiss button directly + // through `scoped_a11y_overrider_`. + bool is_dismiss_button_highlighted_ = false; + + // Updates the current a11y override window when the dismiss button is being + // highlighted. + std::unique_ptr<ScopedA11yOverrideWindowSetter> scoped_a11y_overrider_; }; } // namespace ash
diff --git a/ash/system/toast/system_toast_view_unittest.cc b/ash/system/toast/system_toast_view_unittest.cc index dd6fcd2..d6438b0 100644 --- a/ash/system/toast/system_toast_view_unittest.cc +++ b/ash/system/toast/system_toast_view_unittest.cc
@@ -4,10 +4,12 @@ #include "ash/system/toast/system_toast_view.h" +#include "ash/accessibility/accessibility_controller.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/ash_view_ids.h" #include "ash/public/cpp/system/toast_data.h" #include "ash/resources/vector_icons/vector_icons.h" +#include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/views/controls/button/label_button.h" @@ -106,4 +108,31 @@ GetToastButton(system_toast_view)->GetText()); } +// Tests that the dismiss button can be directly a11y focused by calling +// `ToggleButtonA11yFocus`. +TEST_F(SystemToastViewTest, ToggleA11yFocus) { + Shell::Get()->accessibility_controller()->spoken_feedback().SetEnabled(true); + std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget(); + auto* contents_view = + widget->SetContentsView(std::make_unique<views::View>()); + + // Set up base toast data and add a button. + auto toast_data = CreateBaseToastData(); + toast_data.dismiss_text = u"Button"; + + auto* system_toast_view = contents_view->AddChildView( + std::make_unique<SystemToastView>(toast_data)); + + // Focus ring should not be visible initially. + auto* focus_ring = views::FocusRing::Get(GetToastButton(system_toast_view)); + EXPECT_FALSE(focus_ring->GetVisible()); + + // Toggle a11y focus and test the button's focus ring visiblity. + system_toast_view->ToggleButtonA11yFocus(); + EXPECT_TRUE(focus_ring->GetVisible()); + + system_toast_view->ToggleButtonA11yFocus(); + EXPECT_FALSE(focus_ring->GetVisible()); +} + } // namespace ash
diff --git a/ash/system/toast/toast_manager_impl.cc b/ash/system/toast/toast_manager_impl.cc index 74eedc4..edb1a31 100644 --- a/ash/system/toast/toast_manager_impl.cc +++ b/ash/system/toast/toast_manager_impl.cc
@@ -268,12 +268,10 @@ DCHECK(!current_toast_expiration_timer_->IsRunning()); - if (current_toast_data_->duration != ToastData::kInfiniteDuration) { - current_toast_expiration_timer_->Start( - current_toast_data_->duration, - base::BindRepeating(&ToastManagerImpl::CloseAllToastsWithAnimation, - base::Unretained(this))); - } + current_toast_expiration_timer_->Start( + current_toast_data_->duration, + base::BindRepeating(&ToastManagerImpl::CloseAllToastsWithAnimation, + base::Unretained(this))); base::UmaHistogramEnumeration("Ash.NotifierFramework.Toast.ShownCount", current_toast_data_->catalog_name);
diff --git a/ash/system/toast/toast_manager_unittest.cc b/ash/system/toast/toast_manager_unittest.cc index bec4ed5..d330305 100644 --- a/ash/system/toast/toast_manager_unittest.cc +++ b/ash/system/toast/toast_manager_unittest.cc
@@ -109,6 +109,7 @@ // Start in the ACTIVE (logged-in) state. ChangeLockState(false); + SetShouldLockScreenAutomatically(false); } bool AreSideAlignedToastsEnabled() const { return GetParam(); } @@ -209,11 +210,18 @@ testing::Bool() /* AreSideAlignedToastsEnabled() */); TEST_P(ToastManagerImplTest, ShowAndCloseAutomatically) { - ShowToast("DUMMY", base::Milliseconds(10)); + // A toast with custom duration closes after its duration plus one second. + base::TimeDelta custom_duration = base::Milliseconds(10); + ShowToast("id", custom_duration); + EXPECT_TRUE(GetCurrentOverlay()); + task_environment()->FastForwardBy(custom_duration + base::Seconds(1)); + EXPECT_FALSE(GetCurrentOverlay()); - EXPECT_EQ(1, GetToastSerial()); - - task_environment()->FastForwardBy(base::Milliseconds(1000)); + // A toast with "infinite" duration closes after its duration plus one second. + ShowToast("id", ToastData::kInfiniteDuration); + EXPECT_TRUE(GetCurrentOverlay()); + task_environment()->FastForwardBy(ToastData::kInfiniteDuration + + base::Seconds(1)); EXPECT_FALSE(GetCurrentOverlay()); }
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index d5f7c2f1..d16af78 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -5142,46 +5142,6 @@ EXPECT_TRUE(wallpaper_has_color(kSunsetImageColor)); } -// TODO(b/309020135): Remove this test after -// `kTimeOfDayWallpaperForcedAutoSchedule` is launched. -TEST_P(WallpaperControllerAutoScheduleTest, - DoesNotUpdateTimeOfDayWallpaperWithAutoColorModeOff) { - if (!IsTimeOfDayEnabled()) { - return; - } - - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {}, {features::kTimeOfDayWallpaperForcedAutoSchedule}); - const auto backdrop_image_data = TimeOfDayImageSet(); - client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId, - backdrop_image_data); - - SimulateUserLogin(kAccountId1); - Shell::Get()->dark_light_mode_controller()->SetAutoScheduleEnabled(false); - - OnlineWallpaperParams params( - kAccountId1, wallpaper_constants::kTimeOfDayWallpaperCollectionId, - WALLPAPER_LAYOUT_CENTER_CROPPED, - /*preview_mode=*/false, /*from_user=*/true, - /*daily_refresh_enabled=*/false, - wallpaper_constants::kDefaultTimeOfDayWallpaperUnitId, /*variants=*/{}); - for (const backdrop::Image& backdrop_image : backdrop_image_data) { - params.variants.emplace_back(backdrop_image.asset_id(), - GURL(backdrop_image.image_url()), - backdrop_image.image_type()); - } - - base::test::TestFuture<bool> future; - controller_->SetOnlineWallpaper(params, future.GetCallback()); - ASSERT_TRUE(future.Get()); - - TestWallpaperControllerObserver observer(controller_); - // 7 P.M. - task_environment()->FastForwardBy(base::Hours(17)); - EXPECT_EQ(observer.wallpaper_changed_count(), 0); -} - TEST_P(WallpaperControllerTest, UpdateWallpaperOnScheduleCheckpointChanged_WithReplacedAsset) { SimulateUserLogin(kAccountId1);
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_file_utils.cc b/ash/wallpaper/wallpaper_utils/wallpaper_file_utils.cc index a7f09aa..d08a214 100644 --- a/ash/wallpaper/wallpaper_utils/wallpaper_file_utils.cc +++ b/ash/wallpaper/wallpaper_utils/wallpaper_file_utils.cc
@@ -38,7 +38,7 @@ if (image_metadata.empty()) { return gfx::JPEGCodec::Encode(bitmap, kDefaultEncodingQuality, - &(*output)->data()); + &(*output)->as_vector()); } SkPixmap pixmap; @@ -51,7 +51,7 @@ return gfx::JPEGCodec::Encode(pixmap, kDefaultEncodingQuality, SkJpegEncoder::Downsample::k420, - &(*output)->data(), xmpMetadata.get()); + &(*output)->as_vector(), xmpMetadata.get()); } // Resizes `image` to a resolution which is nearest to `preferred_width` and
diff --git a/ash/webui/demo_mode_app_ui/demo_mode_app_untrusted_ui_unittests.cc b/ash/webui/demo_mode_app_ui/demo_mode_app_untrusted_ui_unittests.cc index 1e79359f..027c891 100644 --- a/ash/webui/demo_mode_app_ui/demo_mode_app_untrusted_ui_unittests.cc +++ b/ash/webui/demo_mode_app_ui/demo_mode_app_untrusted_ui_unittests.cc
@@ -42,8 +42,7 @@ void VerifyDataResponse(std::string expected_response, base::OnceClosure quit_closure, scoped_refptr<base::RefCountedMemory> data_response) { - std::string result(data_response->front_as<char>(), data_response->size()); - EXPECT_EQ(result, expected_response); + EXPECT_EQ(base::as_string_view(*data_response), expected_response); std::move(quit_closure).Run(); } @@ -110,4 +109,4 @@ } } // namespace -} // namespace ash \ No newline at end of file +} // namespace ash
diff --git a/ash/webui/diagnostics_ui/BUILD.gn b/ash/webui/diagnostics_ui/BUILD.gn index e14d0bb..d8b21e10 100644 --- a/ash/webui/diagnostics_ui/BUILD.gn +++ b/ash/webui/diagnostics_ui/BUILD.gn
@@ -15,10 +15,10 @@ "diagnostics_metrics_message_handler.h", "diagnostics_ui.cc", "diagnostics_ui.h", - "url_constants.cc", - "url_constants.h", ] + public_deps = [ ":url_constants" ] + deps = [ "//ash/constants", "//ash/webui/common:chrome_os_webui_config", @@ -40,6 +40,15 @@ ] } +# Url constants pulled out to enable depending on production url constants in +# browser tests. +source_set("url_constants") { + sources = [ + "url_constants.cc", + "url_constants.h", + ] +} + source_set("unit_tests") { testonly = true
diff --git a/ash/webui/diagnostics_ui/resources/BUILD.gn b/ash/webui/diagnostics_ui/resources/BUILD.gn index 8c89592..09591dc 100644 --- a/ash/webui/diagnostics_ui/resources/BUILD.gn +++ b/ash/webui/diagnostics_ui/resources/BUILD.gn
@@ -40,7 +40,7 @@ "network_troubleshooting.ts", "overview_card.ts", "percent_bar_chart.ts", - "realtime_cpu_chart.js", + "realtime_cpu_chart.ts", "routine_result_entry.ts", "routine_result_list.ts", "routine_section.ts", @@ -84,6 +84,7 @@ ts_composite = true ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] + ts_tsconfig_base = "tsconfig_base.json" ts_deps = [ "//ash/webui/common/resources:build_ts", "//ash/webui/common/resources/cr_elements:build_ts",
diff --git a/ash/webui/diagnostics_ui/resources/battery_status_card.ts b/ash/webui/diagnostics_ui/resources/battery_status_card.ts index c893746..24c2127 100644 --- a/ash/webui/diagnostics_ui/resources/battery_status_card.ts +++ b/ash/webui/diagnostics_ui/resources/battery_status_card.ts
@@ -144,6 +144,10 @@ } } + getBatteryChargeStatusForTesting(): BatteryChargeStatus { + return this.batteryChargeStatus; + } + private fetchBatteryInfo(): void { this.systemDataProvider.getBatteryInfo().then( (result: {batteryInfo: BatteryInfo}) => {
diff --git a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html index de4c263..ed5aafe6 100644 --- a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html +++ b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html
@@ -111,12 +111,12 @@ background-color: var(--chart-system-line-color); } </style> -<svg id="chart" width$="[[width_]]" height$="[[height_]]" aria-hidden="true"> +<svg id="chart" width$="[[width]]" height$="[[height]]" aria-hidden="true"> <g id="chartGroup"> <defs> <!-- Define chart area and boundaries --> <clipPath id="defClip"> - <rect width$="[[graphWidth_]]" height$="[[graphHeight_]]"></rect> + <rect width$="[[graphWidth]]" height$="[[graphHeight]]"></rect> </clipPath> <!-- Chart area gradient --> <linearGradient id="user-gradient" gradientTransform="rotate(90)"> @@ -141,7 +141,7 @@ <div id="legend-bar" class="user"></div> <label id="userLabel">[[i18n('cpuUsageUser')]]</label> <span id="userData" aria-labelledby="userLabel"> - [[getPercentageLabel_(user)]] + [[getPercentageLabel(user)]] </span> </div> <div class="divider"></div> @@ -149,7 +149,7 @@ <div id="legend-bar" class="system"></div> <label id="systemLabel">[[i18n('cpuUsageSystem')]]</label> <span id="systemData" aria-labelledby="systemLabel"> - [[getPercentageLabel_(system)]] + [[getPercentageLabel(system)]] </span> </div> </div>
diff --git a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js deleted file mode 100644 index 95b7a69..0000000 --- a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js +++ /dev/null
@@ -1,367 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'chrome://resources/d3/d3.min.js'; -import './diagnostics_shared.css.js'; -import './strings.m.js'; - -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {getTemplate} from './realtime_cpu_chart.html.js'; - -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const RealtimeCpuChartElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); - -/** - * @fileoverview - * 'realtime-cpu-chart' is a moving stacked area graph component used to display - * a realtime cpu usage information. - */ - -/** @polymer */ -export class RealtimeCpuChartElement extends RealtimeCpuChartElementBase { - static get is() { - return 'realtime-cpu-chart'; - } - - static get template() { - return getTemplate(); - } - - static get properties() { - return { - /** @type {number} */ - user: { - type: Number, - value: 0, - }, - - /** @type {number} */ - system: { - type: Number, - value: 0, - }, - - /** @private {number} */ - numDataPoints_: { - type: Number, - value: 50, - }, - - /** - * @private {number} - */ - dataRefreshPerSecond_: { - type: Number, - value: 2, - }, - - /** - * Chart rendering frames per second. - * Strongly preferred to be multiples of dataRefreshPerSecond_. If not, - * there will be a small (hard to notice) jittering at every data refresh. - * @private {number} - */ - framesPerSecond_: { - type: Number, - value: 30, - }, - - /** - * Duration of each frame in milliseconds - * @private {number} - */ - frameDuration_: { - readOnly: true, - type: Number, - computed: 'getFrameDuration_(dataRefreshPerSecond_, framesPerSecond_)', - }, - - /** @private {number} */ - width_: { - type: Number, - value: 560, - }, - - /** @private {number} */ - height_: { - type: Number, - value: 114, - }, - - /** @private {!Object} */ - padding_: { - type: Object, - value: {top: 10, right: 5, bottom: 8, left: 50, tick: 10}, - }, - - /** @private {number} */ - graphWidth_: { - readOnly: true, - type: Number, - computed: 'getGraphDimension_(width_, padding_.left, padding_.right)', - }, - - /** @private {number} */ - graphHeight_: { - readOnly: true, - type: Number, - computed: 'getGraphDimension_(height_, padding_.top, padding_.bottom)', - }, - - }; - } - - /** @override */ - constructor() { - super(); - /** - * Helper function to map range of x coordinates to graph width. - * @private {?d3.LinearScale} - */ - this.xAxisScaleFn_ = null; - - /** - * Helper function to map range of y coordinates to - * graph height. - * @private {?d3.LinearScale} - */ - this.yAxisScaleFn_ = null; - - /** @private {!Array<!Object>} */ - this.data_ = []; - - /** - * DOMHighResTimeStamp of last graph render. - * @private {number} - */ - this.lastRender_ = 0; - - /** - * Current render frame out of this.framesPerSecond_. - * @private {number} - */ - this.currentFrame_ = 0; - - /** - * Y-Values where we should mark ticks for the y-axis on the left. - * @private {!Array<number>} - */ - this.yAxisTicks_ = [0, 25, 50, 75, 100]; - - // Initialize the data array with data outside the chart boundary. - // Note that with side nav DOM manipulation, created() isn't guaranteed to - // be called only once. - this.data_ = []; - for (let i = 0; i < this.numDataPoints_; ++i) { - this.data_.push({user: -1, system: -1}); - } - } - - static get observers() { - return ['setScaling_(graphWidth_)']; - } - - /** @override */ - ready() { - super.ready(); - this.setScaling_(); - this.initializeChart_(); - window.addEventListener('resize', () => this.updateChartWidth_()); - - // Set the initial chart width. - this.updateChartWidth_(); - } - - /** @private */ - updateChartWidth_() { - // parseFloat() is used to convert the string returned by - // getComputedStyleValue() into a number ("642px" --> 642). - const width = parseFloat( - window.getComputedStyle(this).getPropertyValue('--chart-width-nav')); - if (!isNaN(width)) { - this.width_ = width; - } - } - - /** - * Calculate the duration of each frame in milliseconds. - * @return {number} - * @protected - */ - getFrameDuration_() { - assert(this.dataRefreshPerSecond_ > 0); - assert(this.framesPerSecond_ > 0); - assert(this.framesPerSecond_ % this.dataRefreshPerSecond_ === 0); - return 1000 / (this.framesPerSecond_ / this.dataRefreshPerSecond_); - } - - /** - * Get actual graph dimensions after accounting for margins. - * @param {number} base value of dimension. - * @param {...number} margins related to base dimension. - * @return {number} - * @private - */ - getGraphDimension_(base, ...margins) { - return margins.reduce(((acc, margin) => acc - margin), base); - } - - /** - * Sets scaling functions that convert data -> svg coordinates. - * @private - */ - setScaling_() { - // Map y-values [0, 100] to [graphHeight, 0] inverse linearly. - // Data value of 0 will map to graphHeight, 100 maps to 0. - this.yAxisScaleFn_ = - d3.scaleLinear().domain([0, 100]).range([this.graphHeight_, 0]); - - // Map x-values [0, numDataPoints - 3] to [0, graphWidth] linearly. - // Data value of 0 maps to 0, and (numDataPoints - 2) maps to graphWidth. - // numDataPoints is subtracted since 1) data array is zero based, and - // 2) to smooth out the curve function. - this.xAxisScaleFn_ = - d3.scaleLinear().domain([0, this.numDataPoints_ - 2]).range([ - 0, - this.graphWidth_, - ]); - - // Draw the y-axis legend and also draw the horizontal gridlines by - // reversing the ticks back into the chart body. - const chartGroup = d3.select(this.shadowRoot.querySelector('#chartGroup')); - chartGroup.select('#gridLines') - .call( - d3.axisLeft(/** @type {!d3.LinearScale} */ (this.yAxisScaleFn_)) - .tickValues(this.yAxisTicks_) - .tickFormat((y) => this.getPercentageLabel_(y)) - .tickPadding(this.padding_.tick) - .tickSize(-this.graphWidth_), // Extend the ticks into the - // entire graph as gridlines. - ); - } - - /** @private */ - initializeChart_() { - const chartGroup = d3.select(this.shadowRoot.querySelector('#chartGroup')); - - // Position chartGroup inside the margin. - chartGroup.attr( - 'transform', - 'translate(' + this.padding_.left + ',' + this.padding_.top + ')'); - - const plotGroup = d3.select(this.shadowRoot.querySelector('#plotGroup')); - - // Feed data array to the plot group. - plotGroup.datum(this.data_); - - // Select each area and configure the transition for animation. - // d3.transition API @ https://github.com/d3/d3-transition#d3-transition. - // d3.easing API @ https://github.com/d3/d3-ease#api-reference. - plotGroup.select('.user-area') - .transition() - .duration(this.frameDuration_) - .ease(d3.easeLinear); // Linear transition - plotGroup.select('.system-area') - .transition() - .duration(this.frameDuration_) - .ease(d3.easeLinear); // Linear transition - - // Draw initial data and kick off the rendering process. - this.getDataSnapshotAndRedraw_(); - this.render_(0); - } - - /** - * @param {string} areaClass class string for <path> element. - * @return {d3.Area} - * @private - */ - getAreaDefinition_(areaClass) { - return d3 - .area() - // Take the index of each data as x values. - .x((data, i) => this.xAxisScaleFn_(i)) - // Bottom coordinates of each area. System area extends down to -1 - // instead of 0 to avoid the area border from showing up. - .y0(data => this.yAxisScaleFn_( - areaClass === 'system-area' ? -1 : data.system)) - // Top coordinates of each area. - .y1(data => this.yAxisScaleFn_( - areaClass === 'system-area' ? data.system : - data.system + data.user)); - } - - /** - * Takes a snapshot of current CPU readings and appends to the data array for - * redrawing. This method is called after each transition cycle. - * @private - */ - getDataSnapshotAndRedraw_() { - this.data_.push({user: this.user, system: this.system}); - this.data_.shift(); - - const userArea = assert(this.shadowRoot.querySelector(`path.user-area`)); - const systemArea = - assert(this.shadowRoot.querySelector(`path.system-area`)); - d3.select(userArea).attr('d', this.getAreaDefinition_('user-area')); - d3.select(systemArea).attr('d', this.getAreaDefinition_('system-area')); - } - - /** - * @param {number} timeStamp Current time based on DOMHighResTimeStamp. - * @private - */ - render_(timeStamp) { - // Re-render only when this.frameDuration_ has passed since last render. - // If we acquire the animation frame before this, do nothing. - if (timeStamp - this.lastRender_ > this.frameDuration_) { - this.lastRender_ = performance.now(); - - // Get new data and redraw on each cycle. - const framesPerCycle = this.framesPerSecond_ / this.dataRefreshPerSecond_; - if (this.currentFrame_ === framesPerCycle) { - this.currentFrame_ = 0; - this.getDataSnapshotAndRedraw_(); - } - - const userArea = assert(this.shadowRoot.querySelector(`path.user-area`)); - const systemArea = - assert(this.shadowRoot.querySelector(`path.system-area`)); - - // Calculate the new position. Use this.currentFrame_ + 1 since on frame - // 0, it is already at position 0. - const pos = -1 * ((this.currentFrame_ + 1) / framesPerCycle); - - // Slide it to the left - d3.select(userArea).attr( - 'transform', 'translate(' + this.xAxisScaleFn_(pos) + ',0)'); - d3.select(systemArea) - .attr('transform', 'translate(' + this.xAxisScaleFn_(pos) + ',0)'); - this.currentFrame_++; - } - - // Request another frame. - requestAnimationFrame((timeStamp) => this.render_(timeStamp)); - } - - /** - * @param {number} value of percentage. - * @return {string} i18n string for the percentage value. - * @private - */ - getPercentageLabel_(value) { - return loadTimeData.getStringF('percentageLabel', value); - } -} - -customElements.define(RealtimeCpuChartElement.is, RealtimeCpuChartElement);
diff --git a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.ts b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.ts new file mode 100644 index 0000000..03ff010 --- /dev/null +++ b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.ts
@@ -0,0 +1,332 @@ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './diagnostics_shared.css.js'; +import './strings.m.js'; +import 'chrome://resources/d3/d3.min.js'; + +import {PolymerElementProperties} from '//resources/polymer/v3_0/polymer/interfaces.js'; +import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; +import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {assert} from 'chrome://resources/js/assert.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './realtime_cpu_chart.html.js'; + +const RealtimeCpuChartElementBase = I18nMixin(PolymerElement); + +/** + * @fileoverview + * 'realtime-cpu-chart' is a moving stacked area graph component used to display + * a realtime cpu usage information. + */ + +export class RealtimeCpuChartElement extends RealtimeCpuChartElementBase { + static get is(): 'realtime-cpu-chart' { + return 'realtime-cpu-chart' as const; + } + + static get template(): HTMLTemplateElement { + return getTemplate(); + } + + static get properties(): PolymerElementProperties { + return { + user: { + type: Number, + value: 0, + }, + + system: { + type: Number, + value: 0, + }, + + numDataPoints: { + type: Number, + value: 50, + }, + + dataRefreshPerSecond: { + type: Number, + value: 2, + }, + + /** + * Chart rendering frames per second. + * Strongly preferred to be multiples of dataRefreshPerSecond. If not, + * there will be a small (hard to notice) jittering at every data refresh. + */ + framesPerSecond: { + type: Number, + value: 30, + }, + + /** + * Duration of each frame in milliseconds. + */ + frameDuration: { + readOnly: true, + type: Number, + computed: 'getFrameDuration(dataRefreshPerSecond, framesPerSecond)', + }, + + width: { + type: Number, + value: 560, + }, + + height: { + type: Number, + value: 114, + }, + + padding: { + type: Object, + value: {top: 10, right: 5, bottom: 8, left: 50, tick: 10}, + }, + + graphWidth: { + readOnly: true, + type: Number, + computed: 'getGraphDimension(width, padding.left, padding.right)', + }, + + graphHeight: { + readOnly: true, + type: Number, + computed: 'getGraphDimension(height, padding.top, padding.bottom)', + }, + + }; + } + + user: number; + system: number; + private numDataPoints: number; + private dataRefreshPerSecond: number; + private framesPerSecond: number; + private frameDuration: number; + private width: number; + private height: number; + private padding: + {top: number, right: number, bottom: number, left: number, tick: number}; + private graphWidth: number; + private graphHeight: number; + // Helper function to map range of x coordinates to graph width. + private xAxisScaleFn: d3.ScaleLinear<number, number> = d3.scaleLinear(); + // Helper function to map range of y coordinates to graph height. + private yAxisScaleFn: d3.ScaleLinear<number, number> = d3.scaleLinear(); + private data: Array<{user: number, system: number}> = []; + // DOMHighResTimeStamp of last graph render. + private lastRender: number = 0; + // Current render frame out of this.framesPerSecond. + private currentFrame: number = 0; + // Y-Values where we should mark ticks for the y-axis on the left. + private yAxisTicks: number[] = [0, 25, 50, 75, 100]; + + constructor() { + super(); + + // Initialize the data array with data outside the chart boundary. + // Note that with side nav DOM manipulation, created() isn't guaranteed to + // be called only once. + this.data = []; + for (let i = 0; i < this.numDataPoints; ++i) { + this.data.push({user: -1, system: -1}); + } + } + + static get observers(): string[] { + return ['setScaling(graphWidth)']; + } + + override ready(): void { + super.ready(); + this.setScaling(); + this.initializeChart(); + window.addEventListener('resize', () => this.updateChartWidth()); + + // Set the initial chart width. + this.updateChartWidth(); + } + + private updateChartWidth(): void { + // parseFloat() is used to convert the string returned by + // getComputedStyleValue() into a number ("642px" --> 642). + const width = parseFloat( + window.getComputedStyle(this).getPropertyValue('--chart-width-nav')); + if (!isNaN(width)) { + this.width = width; + } + } + + /** + * Calculate the duration of each frame in milliseconds. + */ + protected getFrameDuration(): number { + assert(this.dataRefreshPerSecond > 0); + assert(this.framesPerSecond > 0); + assert(this.framesPerSecond % this.dataRefreshPerSecond === 0); + return 1000 / (this.framesPerSecond / this.dataRefreshPerSecond); + } + + /** + * Get actual graph dimensions after accounting for margins. + */ + private getGraphDimension(base: number, ...margins: number[]): number { + return margins.reduce(((acc, margin) => acc - margin), base); + } + + /** + * Sets scaling functions that convert data -> svg coordinates. + */ + private setScaling(): void { + // Map y-values [0, 100] to [graphHeight, 0] inverse linearly. + // Data value of 0 will map to graphHeight, 100 maps to 0. + this.yAxisScaleFn = + d3.scaleLinear().domain([0, 100]).range([this.graphHeight, 0]); + + // Map x-values [0, numDataPoints - 3] to [0, graphWidth] linearly. + // Data value of 0 maps to 0, and (numDataPoints - 2) maps to graphWidth. + // numDataPoints is subtracted since 1) data array is zero based, and + // 2) to smooth out the curve function. + this.xAxisScaleFn = + d3.scaleLinear().domain([0, this.numDataPoints - 2]).range([ + 0, + this.graphWidth, + ]); + + // Draw the y-axis legend and also draw the horizontal gridlines by + // reversing the ticks back into the chart body. + const chartGroup: d3.Selection<Element|null, unknown, null, undefined>|any = + d3.select(this.shadowRoot!.querySelector('#chartGroup')); + assert(chartGroup); + chartGroup.select('#gridLines') + .call( + d3.axisLeft(this.yAxisScaleFn) + .tickValues(this.yAxisTicks) + .tickFormat((y) => this.getPercentageLabel((y as number))) + .tickPadding(this.padding.tick) + .tickSize(-this.graphWidth), // Extend the ticks into the + // entire graph as gridlines. + ); + } + + private initializeChart(): void { + const chartGroup: d3.Selection<Element|null, unknown, null, undefined> = + d3.select(this.shadowRoot!.querySelector('#chartGroup')); + assert(chartGroup); + + // Position chartGroup inside the margin. + chartGroup.attr( + 'transform', `translate(${this.padding.left},${this.padding.top})`); + + const plotGroup: d3.Selection<Element|null, unknown, null, undefined> = + d3.select(this.shadowRoot!.querySelector('#plotGroup')); + assert(plotGroup); + + // Feed data array to the plot group. + plotGroup.datum(this.data); + + // Select each area and configure the transition for animation. + // d3.transition API @ https://github.com/d3/d3-transition#d3-transition. + // d3.easing API @ https://github.com/d3/d3-ease#api-reference. + plotGroup.select('.user-area') + .transition() + .duration(this.frameDuration) + .ease((t: number) => +t); // Linear transition + plotGroup.select('.system-area') + .transition() + .duration(this.frameDuration) + .ease((t: number) => +t); // Linear transition + + // Draw initial data and kick off the rendering process. + this.getDataSnapshotAndRedraw(); + this.render(/*timeStamp=*/ 0); + } + + private getAreaDefinition(areaClass: string): + d3.ValueFn<SVGPathElement, any, any> { + return d3 + .area() + // Take the index of each data as x values. + .x((_, i) => this.xAxisScaleFn(i)) + // Bottom coordinates of each area. System area extends down to -1 + // instead of 0 to avoid the area border from showing up. + .y0((data: any) => this?.yAxisScaleFn( + areaClass === 'system-area' ? -1 : data?.system)) + // Top coordinates of each area. + .y1((data: any) => this?.yAxisScaleFn( + areaClass === 'system-area' ? data?.system : + data?.system + data?.user)); + } + + /** + * Takes a snapshot of current CPU readings and appends to the data array for + * redrawing. This method is called after each transition cycle. + */ + private getDataSnapshotAndRedraw(): void { + this.data.push({user: this.user, system: this.system}); + this.data.shift(); + + const userArea: d3.Selection<Element|null, unknown, null, undefined>|any = + this.shadowRoot!.querySelector(`path.user-area`); + assert(userArea); + const systemArea: d3.Selection<Element|null, unknown, null, undefined>|any = + this.shadowRoot!.querySelector(`path.system-area`); + assert(systemArea); + d3.select(userArea).attr('d', this.getAreaDefinition('user-area')); + d3.select(systemArea).attr('d', this.getAreaDefinition('system-area')); + } + + + private render(timeStamp: number): void { + // Re-render only when this.frameDuration has passed since last render. + // If we acquire the animation frame before this, do nothing. + if (timeStamp - this.lastRender > this.frameDuration) { + this.lastRender = performance.now(); + + // Get new data and redraw on each cycle. + const framesPerCycle = this.framesPerSecond / this.dataRefreshPerSecond; + if (this.currentFrame === framesPerCycle) { + this.currentFrame = 0; + this.getDataSnapshotAndRedraw(); + } + + const userArea: d3.Selection<Element|null, unknown, null, undefined>|any = + this.shadowRoot!.querySelector(`path.user-area`); + assert(userArea); + const systemArea: d3.Selection<Element|null, unknown, null, undefined>| + any = this.shadowRoot!.querySelector(`path.system-area`); + assert(systemArea); + + // Calculate the new position. Use this.currentFrame + 1 since on frame + // 0, it is already at position 0. + const pos = -1 * ((this.currentFrame + 1) / framesPerCycle); + + // Slide it to the left + d3.select(userArea).attr( + 'transform', 'translate(' + this.xAxisScaleFn(pos) + ',0)'); + d3.select(systemArea) + .attr('transform', 'translate(' + this.xAxisScaleFn(pos) + ',0)'); + this.currentFrame++; + } + + // Request another frame. + requestAnimationFrame((timeStamp) => this.render(timeStamp)); + } + + private getPercentageLabel(value: number): string { + return loadTimeData.getStringF('percentageLabel', value); + } +} + +declare global { + interface HTMLElementTagNameMap { + [RealtimeCpuChartElement.is]: RealtimeCpuChartElement; + } +} + +customElements.define(RealtimeCpuChartElement.is, RealtimeCpuChartElement);
diff --git a/ash/webui/diagnostics_ui/resources/tsconfig_base.json b/ash/webui/diagnostics_ui/resources/tsconfig_base.json index 9ef04d0..613a4ca 100644 --- a/ash/webui/diagnostics_ui/resources/tsconfig_base.json +++ b/ash/webui/diagnostics_ui/resources/tsconfig_base.json
@@ -1,6 +1,7 @@ { "extends": "../../../../tools/typescript/tsconfig_base_polymer.json", "compilerOptions": { + "allowUmdGlobalAccess": true, "typeRoots": [ "../../../../third_party/node/node_modules/@types" ], "types": [ "d3" ] }
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_collections_element.ts b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_collections_element.ts index fc3a3eb..7f08866 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_collections_element.ts +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_collections_element.ts
@@ -172,7 +172,7 @@ return {type: TileType.LOADING, id: kLocalCollectionId}; } - if (!localImages || localImages.length === 0) { + if (!isNonEmptyArray(localImages)) { // TODO(b/282050032): After Jelly is launched, remove the preview image. return { count: getCountText(0), @@ -669,10 +669,18 @@ localImages: Array<FilePath|DefaultImageSymbol>|null, localImagesLoading: boolean, localImageData: Record<FilePath['path']|DefaultImageSymbol, Url>) { - const tile = getLocalTile(localImages, localImagesLoading, localImageData); + const newLocalTile = + getLocalTile(localImages, localImagesLoading, localImageData); const index = this.tiles_.findIndex(tile => tile.id === kLocalCollectionId); assert(index >= 0, 'could not find local tile'); - this.set(`tiles_.${index}`, tile); + const currentLocalTile = this.get(`tiles_.${index}`); + if (this.isLoadingTile_(currentLocalTile) || + !isNonEmptyArray(localImages) || this.isLocalTile_(newLocalTile)) { + // Displays loading tile only when no preview images have been fetched. If + // the local tile has already had some preview images, do not display + // loading again to avoid flickering. + this.set(`tiles_.${index}`, newLocalTile); + } } /** Navigate to the correct route based on user selection. */
diff --git a/ash/webui/shimless_rma/resources/reimaging_device_information_page.ts b/ash/webui/shimless_rma/resources/reimaging_device_information_page.ts index 61341c1..0883a6e 100644 --- a/ash/webui/shimless_rma/resources/reimaging_device_information_page.ts +++ b/ash/webui/shimless_rma/resources/reimaging_device_information_page.ts
@@ -16,7 +16,7 @@ import {getShimlessRmaService} from './mojo_interface_provider.js'; import {getTemplate} from './reimaging_device_information_page.html.js'; import {FeatureLevel, ShimlessRmaServiceInterface, StateResult} from './shimless_rma.mojom-webui.js'; -import {disableNextButton, enableNextButton, focusPageTitle, isComplianceCheckEnabled, isSkuDescriptionEnabled} from './shimless_rma_util.js'; +import {disableNextButton, enableNextButton, focusPageTitle, isComplianceCheckEnabled} from './shimless_rma_util.js'; /** * @fileoverview @@ -285,10 +285,8 @@ return this.shimlessRmaService.getSkuDescriptionList(); }) .then((result: {skuDescriptions: string[]}) => { - // The SKU description list can be empty if the backend disables this - // feature. - if (isSkuDescriptionEnabled() && - this.skus.length === result.skuDescriptions.length) { + // The SKU description list can be empty. + if (this.skus.length === result.skuDescriptions.length) { this.skus = this.skus.map( (sku, index) => `${sku}: ${result.skuDescriptions[index]}`); }
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_util.ts b/ash/webui/shimless_rma/resources/shimless_rma_util.ts index cae5504..fe6a969 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma_util.ts +++ b/ash/webui/shimless_rma/resources/shimless_rma_util.ts
@@ -103,10 +103,3 @@ export function isComplianceCheckEnabled(): boolean { return loadTimeData.getBoolean('complianceCheckEnabled'); } - -/** - * @returns whether the "SKU description" flag is enabled. - */ -export function isSkuDescriptionEnabled(): boolean { - return loadTimeData.getBoolean('skuDescriptionEnabled'); -}
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc index ae3d961..af83a57 100644 --- a/ash/webui/shimless_rma/shimless_rma.cc +++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -425,8 +425,6 @@ base::FeatureList::IsEnabled(features::kShimlessRMAOsUpdate)); html_source->AddBoolean("complianceCheckEnabled", features::IsShimlessRMAComplianceCheckEnabled()); - html_source->AddBoolean("skuDescriptionEnabled", - features::IsShimlessRMASkuDescriptionEnabled()); html_source->AddBoolean("3pDiagnosticsEnabled", features::IsShimlessRMA3pDiagnosticsEnabled()); }
diff --git a/ash/wm/snap_group/snap_group_controller.cc b/ash/wm/snap_group/snap_group_controller.cc index 0ded1881..cc39187 100644 --- a/ash/wm/snap_group/snap_group_controller.cc +++ b/ash/wm/snap_group/snap_group_controller.cc
@@ -79,6 +79,11 @@ return nullptr; } + // We only allow snap group to be created if the windows fit the work area. + if (!CanWindowsFitInWorkArea(window1, window2)) { + return nullptr; + } + if (base::Contains(window_to_snap_group_map_, window1) || base::Contains(window_to_snap_group_map_, window2)) { return nullptr;
diff --git a/ash/wm/snap_group/snap_group_unittest.cc b/ash/wm/snap_group/snap_group_unittest.cc index 0d762d8..bdb3198 100644 --- a/ash/wm/snap_group/snap_group_unittest.cc +++ b/ash/wm/snap_group/snap_group_unittest.cc
@@ -2478,8 +2478,81 @@ // Activate `w1`. Test we don't create a snap group. wm::ActivateWindow(w1.get()); - EXPECT_FALSE( - SnapGroupController::Get()->AreWindowsInSnapGroup(w1.get(), w2.get())); +} + +// Tests that when the auto-snapped window has minimum size that doesn't fit the +// work area, we adjust the divider and window bounds. +TEST_F(SnapGroupTest, AutoSnapWindowWithMinimumSize) { + // Test with both the bottom and side shelf. + for (const auto& shelf_alignment : + {ShelfAlignment::kBottom, ShelfAlignment::kLeft}) { + SCOPED_TRACE(base::StringPrintf("Shelf alignment = %d", + static_cast<int>(shelf_alignment))); + GetPrimaryShelf()->SetAlignment(shelf_alignment); + // Create `w2` so it doesn't fit on the other side of `w1`. + std::unique_ptr<aura::Window> w1(CreateAppWindow()); + aura::test::TestWindowDelegate delegate2; + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, /*id=*/0, gfx::Rect(800, 600))); + const gfx::Rect work_area(work_area_bounds()); + delegate2.set_minimum_size( + gfx::Size(work_area.width() * 0.4f, work_area.height())); + + // Snap `w1` to start partial overview. + SnapOneTestWindow(w1.get(), WindowStateType::kPrimarySnapped, + chromeos::kTwoThirdSnapRatio); + EXPECT_TRUE(OverviewController::Get()->InOverviewSession()); + + // Select `w2` to be auto-snapped. + ClickOverviewItem(GetEventGenerator(), w2.get()); + EXPECT_TRUE( + SnapGroupController::Get()->AreWindowsInSnapGroup(w1.get(), w2.get())); + auto* snap_group = + SnapGroupController::Get()->GetSnapGroupForGivenWindow(w1.get()); + + // Expect `w2` is snapped at its minimum width and `w1` and the divider are + // adjusted to fit. + EXPECT_NEAR(work_area.width() * 0.4f, w2->GetBoundsInScreen().width(), 1); + UnionBoundsEqualToWorkAreaBounds(w1.get(), w2.get(), + snap_group->snap_group_divider()); + } +} + +// Tests that when both windows have minimum sizes, we don't create a snap +// group. +TEST_F(SnapGroupTest, AutoSnapBothWindowsWithMinimumSizes) { + // Test with both the bottom and side shelf. + for (const auto& shelf_alignment : + {ShelfAlignment::kBottom, ShelfAlignment::kLeft}) { + SCOPED_TRACE(base::StringPrintf("Shelf alignment = %d", + static_cast<int>(shelf_alignment))); + GetPrimaryShelf()->SetAlignment(shelf_alignment); + // Create `w1` and `w2` both with minimum size 0.6f. + aura::test::TestWindowDelegate delegate1; + aura::test::TestWindowDelegate delegate2; + std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithDelegate( + &delegate1, /*id=*/-1, gfx::Rect(800, 600))); + std::unique_ptr<aura::Window> w2(CreateTestWindowInShellWithDelegate( + &delegate2, /*id=*/0, gfx::Rect(800, 600))); + const gfx::Rect work_area(work_area_bounds()); + const int min_width = work_area.width() * 0.6f; + delegate1.set_minimum_size(gfx::Size(min_width, work_area.height())); + delegate2.set_minimum_size(gfx::Size(min_width, work_area.height())); + + // Snap `w1` to 2/3. + SnapOneTestWindow(w1.get(), WindowStateType::kPrimarySnapped, + chromeos::kTwoThirdSnapRatio); + const gfx::Rect w1_bounds = w1->GetBoundsInScreen(); + EXPECT_TRUE(OverviewController::Get()->InOverviewSession()); + + // Select `w2` to be auto-snapped. Since it tries to snap to 0.6f, but `w1` + // can't fit in the other side, we don't create a group. + ClickOverviewItem(GetEventGenerator(), w2.get()); + EXPECT_NEAR(min_width, w2->GetBoundsInScreen().width(), 1); + EXPECT_EQ(w1_bounds.width(), w1->GetBoundsInScreen().width()); + EXPECT_FALSE( + SnapGroupController::Get()->AreWindowsInSnapGroup(w1.get(), w2.get())); + } } // -----------------------------------------------------------------------------
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc index 584d401..bbe06d35 100644 --- a/ash/wm/splitview/split_view_utils.cc +++ b/ash/wm/splitview/split_view_utils.cc
@@ -979,6 +979,21 @@ split_view_controller->split_view_divider()->divider_widget(); } +bool CanWindowsFitInWorkArea(aura::Window* window1, aura::Window* window2) { + DCHECK_EQ(window1->GetRootWindow(), window2->GetRootWindow()); + aura::Window* root_window = window1->GetRootWindow(); + const bool horizontal = IsLayoutHorizontal(root_window); + const gfx::Rect work_area = display::Screen::GetScreen() + ->GetDisplayNearestWindow(root_window) + .work_area(); + const int work_area_length = + horizontal ? work_area.width() : work_area.height(); + return GetMinimumWindowLength(window1, horizontal) + + GetMinimumWindowLength(window2, horizontal) + + kSplitviewDividerShortSideLength <= + work_area_length; +} + ASH_EXPORT std::string BuildWindowLayoutCompleteOnSessionExitHistogram() { std::string histogram_name(kHistogramPrefix); histogram_name.append(kWindowLayoutCompleteOnSessionExitRootWord);
diff --git a/ash/wm/splitview/split_view_utils.h b/ash/wm/splitview/split_view_utils.h index c5e46bc..b79b5f5 100644 --- a/ash/wm/splitview/split_view_utils.h +++ b/ash/wm/splitview/split_view_utils.h
@@ -302,6 +302,11 @@ // `UpdateSnappedBounds()` directly. bool ShouldConsiderDivider(aura::Window* window); +// Returns true if the minimum size of `window1` and `window2` and the divider +// width can fit in the work area. The windows should belong to the same root +// window. +bool CanWindowsFitInWorkArea(aura::Window* window1, aura::Window* window2); + // Builds the full histogram that records whether the window layout completes on // `SplitViewOverviewSession` exit. The full histogram is shown in the example // below:
diff --git a/base/android/jni_conversions.cc b/base/android/jni_conversions.cc index ab613e6..a0a34ef 100644 --- a/base/android/jni_conversions.cc +++ b/base/android/jni_conversions.cc
@@ -14,85 +14,62 @@ namespace jni_zero { template <> -BASE_EXPORT std::string FromJniType<std::string, jstring>( +BASE_EXPORT std::string FromJniType<std::string>( JNIEnv* env, - const JavaRef<jstring>& input) { - return base::android::ConvertJavaStringToUTF8(env, input); + const JavaRef<jobject>& input) { + return base::android::ConvertJavaStringToUTF8( + env, static_cast<jstring>(input.obj())); } template <> -BASE_EXPORT ScopedJavaLocalRef<jstring> ToJniType<std::string, jstring>( +BASE_EXPORT ScopedJavaLocalRef<jobject> ToJniType<std::string>( JNIEnv* env, const std::string& input) { return base::android::ConvertUTF8ToJavaString(env, input); } template <> -BASE_EXPORT ScopedJavaLocalRef<jstring> ToJniType<const char*>( +BASE_EXPORT ScopedJavaLocalRef<jobject> ToJniType<const char*>( JNIEnv* env, const char* const& input) { return base::android::ConvertUTF8ToJavaString(env, input); } template <> -BASE_EXPORT std::u16string FromJniType<std::u16string, jstring>( +BASE_EXPORT std::u16string FromJniType<std::u16string>( JNIEnv* env, - const JavaRef<jstring>& input) { - return base::android::ConvertJavaStringToUTF16(env, input); + const JavaRef<jobject>& input) { + return base::android::ConvertJavaStringToUTF16( + env, static_cast<jstring>(input.obj())); } template <> -BASE_EXPORT ScopedJavaLocalRef<jstring> ToJniType<std::u16string, jstring>( +BASE_EXPORT ScopedJavaLocalRef<jobject> ToJniType<std::u16string>( JNIEnv* env, const std::u16string& input) { return base::android::ConvertUTF16ToJavaString(env, input); } template <> -BASE_EXPORT ScopedJavaLocalRef<jstring> ToJniType<std::u16string_view, jstring>( +BASE_EXPORT ScopedJavaLocalRef<jobject> ToJniType<std::u16string_view>( JNIEnv* env, const std::u16string_view& input) { return base::android::ConvertUTF16ToJavaString(env, input); } template <> -BASE_EXPORT base::FilePath FromJniType<base::FilePath, jstring>( +BASE_EXPORT base::FilePath FromJniType<base::FilePath>( JNIEnv* env, - const JavaRef<jstring>& input) { - return base::FilePath(base::android::ConvertJavaStringToUTF8(env, input)); + const JavaRef<jobject>& input) { + return base::FilePath(base::android::ConvertJavaStringToUTF8( + env, static_cast<jstring>(input.obj()))); } template <> -BASE_EXPORT ScopedJavaLocalRef<jstring> ToJniType<base::FilePath, jstring>( +BASE_EXPORT ScopedJavaLocalRef<jobject> ToJniType<base::FilePath>( JNIEnv* env, const base::FilePath& input) { return base::android::ConvertUTF8ToJavaString(env, input.value()); } -// Specialized conversions for std::optional<std::basic_string<T>> since jstring -// is a nullable type but std::basic_string<T> is not. -template <> -BASE_EXPORT std::optional<std::string> -FromJniType<std::optional<std::string>, jstring>( - JNIEnv* env, - const JavaRef<jstring>& j_string) { - if (!j_string) { - return std::nullopt; - } - return std::optional<std::string>( - FromJniType<std::string, jstring>(env, j_string)); -} - -template <> -BASE_EXPORT std::optional<std::u16string> -FromJniType<std::optional<std::u16string>, jstring>( - JNIEnv* env, - const JavaRef<jstring>& j_string) { - if (!j_string) { - return std::nullopt; - } - return std::optional<std::u16string>( - FromJniType<std::u16string, jstring>(env, j_string)); -} - } // namespace jni_zero
diff --git a/base/check.h b/base/check.h index 14df5b96..e3ba8f0 100644 --- a/base/check.h +++ b/base/check.h
@@ -15,7 +15,6 @@ #include "base/location.h" #include "base/macros/if.h" #include "base/macros/is_empty.h" -#include "base/memory/raw_ptr.h" #include "base/not_fatal_until.h" // This header defines the CHECK, DCHECK, and DPCHECK macros.
diff --git a/base/i18n/icu_mergeable_data_file.cc b/base/i18n/icu_mergeable_data_file.cc index 07b71e4..05b7e07 100644 --- a/base/i18n/icu_mergeable_data_file.cc +++ b/base/i18n/icu_mergeable_data_file.cc
@@ -44,7 +44,7 @@ IcuMergeableDataFile::HashType ReadHash(const uint8_t* data, size_t offset) { // TODO(crbug/1503551): upgrade to CHECK. - DUMP_WILL_BE_CHECK_EQ(0ul, offset % kHashBytes); + CHECK_EQ(0ul, offset % kHashBytes); IcuMergeableDataFile::HashType hash = 0; for (size_t i = 0; i < kHashBytes; i++) { IcuMergeableDataFile::HashType byte = data[offset + i]; @@ -115,8 +115,8 @@ bool IcuMergeableDataFile::Initialize(File lacros_file, MemoryMappedFile::Region region) { // TODO(crbug/1503551): upgrade to CHECK. - DUMP_WILL_BE_CHECK(region == MemoryMappedFile::Region::kWholeFile); - DUMP_WILL_BE_CHECK(!lacros_file_.IsValid()) + CHECK(region == MemoryMappedFile::Region::kWholeFile); + CHECK(!lacros_file_.IsValid()) << "ICUDataFile::Initialize called twice"; lacros_file_ = std::move(lacros_file); @@ -156,7 +156,7 @@ bool IcuMergeableDataFile::MergeWithAshVersion(const FilePath& ash_file_path) { // Verify the assumption that page size is 4K. // TODO(crbug/1503551): upgrade to CHECK. - DUMP_WILL_BE_CHECK_EQ(sysconf(_SC_PAGESIZE), kPageSize); + CHECK_EQ(sysconf(_SC_PAGESIZE), kPageSize); // Mmap Ash's data file. auto ash_file = MmapAshFile(ash_file_path); @@ -194,7 +194,7 @@ // If `remap` == true, we add the MAP_FIXED option to unmap the // existing map and replace it with the new one in a single operation. // TODO(crbug/1503551): upgrade to CHECK. - DUMP_WILL_BE_CHECK_NE(lacros_data_, nullptr); + CHECK_NE(lacros_data_, nullptr); lacros_data_ = static_cast<uint8_t*>( mmap(lacros_data_, lacros_length_, PROT_READ, MAP_FIXED | MAP_PRIVATE, lacros_file_.GetPlatformFile(), 0)); @@ -260,13 +260,7 @@ const AshMemoryMappedFile& ash_file, const uint8_t* ash_page, const uint8_t* lacros_page) const { - // TODO(crbug/1478718): Remove once the cause of this crash is identified. if (!ash_page || !lacros_page) { - const uint8_t* debug_ash_page = ash_page; - const uint8_t* debug_lacros_page = lacros_page; - base::debug::Alias(&debug_ash_page); - base::debug::Alias(&debug_lacros_page); - base::debug::DumpWithoutCrashing(); return 0; } @@ -382,8 +376,8 @@ // file associated with the file descriptor. int64_t path_len = readlink(proc_path.value().c_str(), path, sizeof(path)); // TODO(crbug/1503551): upgrade to CHECK. - DUMP_WILL_BE_CHECK_NE(path_len, -1); - DUMP_WILL_BE_CHECK_LT(path_len, PATH_MAX); + CHECK_NE(path_len, -1); + CHECK_LT(path_len, PATH_MAX); return FilePath(std::string(path, 0, path_len)); }
diff --git a/base/memory/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc index b43e5091..3ca8854 100644 --- a/base/memory/ref_counted_memory.cc +++ b/base/memory/ref_counted_memory.cc
@@ -13,100 +13,76 @@ bool RefCountedMemory::Equals( const scoped_refptr<RefCountedMemory>& other) const { - return other.get() && size() == other->size() && - (size() == 0 || (memcmp(front(), other->front(), size()) == 0)); + return other && AsSpan() == other->AsSpan(); } RefCountedMemory::RefCountedMemory() = default; - RefCountedMemory::~RefCountedMemory() = default; -const unsigned char* RefCountedStaticMemory::front() const { - return data_; -} - -size_t RefCountedStaticMemory::size() const { - return length_; -} - +RefCountedStaticMemory::RefCountedStaticMemory() = default; RefCountedStaticMemory::~RefCountedStaticMemory() = default; +RefCountedStaticMemory::RefCountedStaticMemory(base::span<const uint8_t> bytes) + : bytes_(bytes) {} + +base::span<const uint8_t> RefCountedStaticMemory::AsSpan() const { + return bytes_; +} + RefCountedBytes::RefCountedBytes() = default; +RefCountedBytes::~RefCountedBytes() = default; -RefCountedBytes::RefCountedBytes(const std::vector<unsigned char>& initializer) - : data_(initializer) {} +RefCountedBytes::RefCountedBytes(std::vector<uint8_t> initializer) + : bytes_(std::move(initializer)) {} -RefCountedBytes::RefCountedBytes(base::span<const unsigned char> initializer) - : data_(initializer.begin(), initializer.end()) {} +RefCountedBytes::RefCountedBytes(base::span<const uint8_t> initializer) + : bytes_(initializer.begin(), initializer.end()) {} -RefCountedBytes::RefCountedBytes(const unsigned char* p, size_t size) - : data_(p, p + size) {} +RefCountedBytes::RefCountedBytes(const uint8_t* p, size_t size) + : bytes_(p, p + size) {} -RefCountedBytes::RefCountedBytes(size_t size) : data_(size, 0) {} +RefCountedBytes::RefCountedBytes(size_t size) : bytes_(size, 0u) {} scoped_refptr<RefCountedBytes> RefCountedBytes::TakeVector( - std::vector<unsigned char>* to_destroy) { + std::vector<uint8_t>* to_destroy) { auto bytes = MakeRefCounted<RefCountedBytes>(); - bytes->data_.swap(*to_destroy); + bytes->bytes_.swap(*to_destroy); return bytes; } -const unsigned char* RefCountedBytes::front() const { - // STL will assert if we do front() on an empty vector, but calling code - // expects a NULL. - return size() ? &data_.front() : nullptr; +base::span<const uint8_t> RefCountedBytes::AsSpan() const { + return bytes_; } -size_t RefCountedBytes::size() const { - return data_.size(); -} - -RefCountedBytes::~RefCountedBytes() = default; - RefCountedString::RefCountedString() = default; - RefCountedString::~RefCountedString() = default; -RefCountedString::RefCountedString(std::string str) : data_(std::move(str)) {} +RefCountedString::RefCountedString(std::string str) : string_(std::move(str)) {} -const unsigned char* RefCountedString::front() const { - return data_.empty() ? nullptr - : reinterpret_cast<const unsigned char*>(data_.data()); -} - -size_t RefCountedString::size() const { - return data_.size(); +base::span<const uint8_t> RefCountedString::AsSpan() const { + return base::as_byte_span(string_); } RefCountedString16::RefCountedString16() = default; - RefCountedString16::~RefCountedString16() = default; RefCountedString16::RefCountedString16(std::u16string str) - : data_(std::move(str)) {} + : string_(std::move(str)) {} -const unsigned char* RefCountedString16::front() const { - return reinterpret_cast<const unsigned char*>(data_.data()); -} - -size_t RefCountedString16::size() const { - return data_.size() * sizeof(char16_t); +base::span<const uint8_t> RefCountedString16::AsSpan() const { + return base::as_byte_span(string_); } RefCountedSharedMemoryMapping::RefCountedSharedMemoryMapping( ReadOnlySharedMemoryMapping mapping) - : mapping_(std::move(mapping)), size_(mapping_.size()) { - DCHECK_GT(size_, 0U); + : mapping_(std::move(mapping)) { + DCHECK_GT(mapping_.size(), 0u); } RefCountedSharedMemoryMapping::~RefCountedSharedMemoryMapping() = default; -const unsigned char* RefCountedSharedMemoryMapping::front() const { - return static_cast<const unsigned char*>(mapping_.memory()); -} - -size_t RefCountedSharedMemoryMapping::size() const { - return size_; +base::span<const uint8_t> RefCountedSharedMemoryMapping::AsSpan() const { + return mapping_.GetMemoryAsSpan<const uint8_t>(); } // static
diff --git a/base/memory/ref_counted_memory.h b/base/memory/ref_counted_memory.h index 8705d9d..aebcebd 100644 --- a/base/memory/ref_counted_memory.h +++ b/base/memory/ref_counted_memory.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/base_export.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/memory/ref_counted.h" #include "base/memory/shared_memory_mapping.h" @@ -23,56 +24,76 @@ // A generic interface to memory. This object is reference counted because most // of its subclasses own the data they carry, and this interface needs to // support heterogeneous containers of these different types of memory. +// +// The RefCountedMemory class provides a const view of the data it holds, as it +// does not require all subclassing implementations to hold mutable data. If a +// mutable view is required, the code must maintain awareness of the subclass +// type, and can access it through there, such as: +// - RefCountedBytes provides `as_vector()` to give mutable access to its data. +// - RefCountedString provides `as_string()` to give mutable access to its data. class BASE_EXPORT RefCountedMemory : public RefCountedThreadSafe<RefCountedMemory> { public: - // Retrieves a pointer to the beginning of the data we point to. If the data - // is empty, this will return NULL. - virtual const unsigned char* front() const = 0; - - // Size of the memory pointed to. - virtual size_t size() const = 0; - - // Returns true if |other| is byte for byte equal. + // Returns true if `other` is byte for byte equal. bool Equals(const scoped_refptr<RefCountedMemory>& other) const; - // Handy method to simplify calling front() with a reinterpret_cast. - template<typename T> const T* front_as() const { - return reinterpret_cast<const T*>(front()); + // Allow explicit conversion to `base::span<const uint8_t>`. Use a span to + // access the data in a safe way, rather than calling `data()` explicitly. + // + // Example: + // ``` + // auto data = base::MakeRefCounted<base::RefCountedBytes>( + // std::vector<uint8_t>{1, 2, 3}); + // base::span<const uint8_t> v = base::span(data); + // v[2] = uint8_t{4}; + // ``` + const uint8_t* data() const LIFETIME_BOUND { return AsSpan().data(); } + size_t size() const { return AsSpan().size(); } + + using iterator = base::span<const uint8_t>::iterator; + iterator begin() const LIFETIME_BOUND { return AsSpan().begin(); } + iterator end() const LIFETIME_BOUND { return AsSpan().end(); } + + // TODO(danakj): Remove all callers and remove this. + const uint8_t* front() const LIFETIME_BOUND { return AsSpan().data(); } + + // The data/size members (or begin/end) give conversion to span already, but + // we provide this operator as an optimization to combine two virtual method + // calls into one. + explicit operator base::span<const uint8_t>() const LIFETIME_BOUND { + return AsSpan(); } - const unsigned char* data() const { return front(); } - - const unsigned char* begin() const { return data(); } - const unsigned char* end() const { return data() + size(); } - protected: friend class RefCountedThreadSafe<RefCountedMemory>; RefCountedMemory(); virtual ~RefCountedMemory(); + + virtual base::span<const uint8_t> AsSpan() const LIFETIME_BOUND = 0; }; -// An implementation of RefCountedMemory, where the ref counting does not -// matter. +// An implementation of RefCountedMemory, for pointing to memory with a static +// lifetime. Since the memory exists for the life of the program, the class can +// not and does not need to take ownership of it. class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory { public: - RefCountedStaticMemory() : data_(nullptr), length_(0) {} + RefCountedStaticMemory(); + explicit RefCountedStaticMemory(base::span<const uint8_t> bytes); + + // TODO(crbug.com/40284755): Remove this overload, use the span ctor instead. RefCountedStaticMemory(const void* data, size_t length) - : data_(static_cast<const unsigned char*>(length ? data : nullptr)), - length_(length) {} + : UNSAFE_BUFFERS(bytes_(static_cast<const uint8_t*>(data), length)) {} RefCountedStaticMemory(const RefCountedStaticMemory&) = delete; RefCountedStaticMemory& operator=(const RefCountedStaticMemory&) = delete; - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - private: ~RefCountedStaticMemory() override; - const unsigned char* data_; - size_t length_; + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + + base::span<const uint8_t> bytes_; }; // An implementation of RefCountedMemory, where the data is stored in a STL @@ -82,11 +103,13 @@ RefCountedBytes(); // Constructs a RefCountedBytes object by copying from |initializer|. - explicit RefCountedBytes(const std::vector<unsigned char>& initializer); - explicit RefCountedBytes(base::span<const unsigned char> initializer); + explicit RefCountedBytes(std::vector<uint8_t> initializer); + explicit RefCountedBytes(base::span<const uint8_t> initializer); // Constructs a RefCountedBytes object by copying |size| bytes from |p|. - RefCountedBytes(const unsigned char* p, size_t size); + // + // TODO(crbug.com/40284755): Remove this overload, use the span ctor instead. + RefCountedBytes(const uint8_t* p, size_t size); // Constructs a RefCountedBytes object by zero-initializing a new vector of // |size| bytes. @@ -98,28 +121,22 @@ // Constructs a RefCountedBytes object by performing a swap. (To non // destructively build a RefCountedBytes, use the constructor that takes a // vector.) + // + // TODO(danakj): This can be removed, as callers can now move() the vector to + // the ctor instead. static scoped_refptr<RefCountedBytes> TakeVector( - std::vector<unsigned char>* to_destroy); + std::vector<uint8_t>* to_destroy); - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - const std::vector<unsigned char>& data() const { return data_; } - std::vector<unsigned char>& data() { return data_; } - - // Non-const versions of front() and front_as() that are simply shorthand for - // data().data(). - unsigned char* front() { return data_.data(); } - template <typename T> - T* front_as() { - return reinterpret_cast<T*>(front()); - } + const std::vector<uint8_t>& as_vector() const { return bytes_; } + std::vector<uint8_t>& as_vector() { return bytes_; } private: ~RefCountedBytes() override; - std::vector<unsigned char> data_; + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + + std::vector<uint8_t> bytes_; }; // An implementation of RefCountedMemory, where the bytes are stored in a STL @@ -132,17 +149,16 @@ RefCountedString(const RefCountedString&) = delete; RefCountedString& operator=(const RefCountedString&) = delete; - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - const std::string& data() const { return data_; } - std::string& data() { return data_; } + const std::string& as_string() const { return string_; } + std::string& as_string() { return string_; } private: ~RefCountedString() override; - std::string data_; + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + + std::string string_; }; // An implementation of RefCountedMemory, where the bytes are stored in a @@ -155,15 +171,16 @@ RefCountedString16(const RefCountedString16&) = delete; RefCountedString16& operator=(const RefCountedString16&) = delete; - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - - protected: - ~RefCountedString16() override; + const std::u16string& as_string() const { return string_; } + std::u16string& as_string() { return string_; } private: - std::u16string data_; + ~RefCountedString16() override; + + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + + std::u16string string_; }; // An implementation of RefCountedMemory, where the bytes are stored in @@ -178,20 +195,18 @@ RefCountedSharedMemoryMapping& operator=( const RefCountedSharedMemoryMapping&) = delete; - // Convenience method to map all of |region| and take ownership of the - // mapping. Returns an empty scoped_refptr if the map operation fails. + // Convenience method to map all of `region` and take ownership of the + // mapping. Returns a null `scoped_refptr` if the map operation fails. static scoped_refptr<RefCountedSharedMemoryMapping> CreateFromWholeRegion( const ReadOnlySharedMemoryRegion& region); - // RefCountedMemory: - const unsigned char* front() const override; - size_t size() const override; - private: ~RefCountedSharedMemoryMapping() override; + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + const ReadOnlySharedMemoryMapping mapping_; - const size_t size_; }; } // namespace base
diff --git a/base/memory/ref_counted_memory_unittest.cc b/base/memory/ref_counted_memory_unittest.cc index f347249..f2ffe2c 100644 --- a/base/memory/ref_counted_memory_unittest.cc +++ b/base/memory/ref_counted_memory_unittest.cc
@@ -13,27 +13,24 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::Each; using testing::ElementsAre; namespace base { -namespace { - -void ConvertToByteSpanAndCheckSize(span<const uint8_t> data, - size_t expected_size) { - EXPECT_EQ(expected_size, data.size()); -} - -} // namespace - TEST(RefCountedMemoryUnitTest, RefCountedStaticMemory) { - auto mem = MakeRefCounted<RefCountedStaticMemory>("static mem00", 10); + { + auto mem = MakeRefCounted<RefCountedStaticMemory>( + base::byte_span_from_cstring("static mem")); - EXPECT_EQ(10U, mem->size()); - EXPECT_EQ("static mem", std::string(mem->front_as<char>(), mem->size())); + EXPECT_THAT(base::span(*mem), + ElementsAre('s', 't', 'a', 't', 'i', 'c', ' ', 'm', 'e', 'm')); + } + { + auto mem = MakeRefCounted<RefCountedStaticMemory>("static mem00", 10); - ConvertToByteSpanAndCheckSize(*mem, 10); + EXPECT_THAT(base::span(*mem), + ElementsAre('s', 't', 'a', 't', 'i', 'c', ' ', 'm', 'e', 'm')); + } } TEST(RefCountedMemoryUnitTest, RefCountedBytes) { @@ -44,54 +41,40 @@ EXPECT_EQ(0U, data.size()); - ASSERT_EQ(2U, mem->size()); - EXPECT_EQ(45U, mem->front()[0]); - EXPECT_EQ(99U, mem->front()[1]); + EXPECT_THAT(base::span(*mem), ElementsAre(45, 99)); scoped_refptr<RefCountedMemory> mem2; { - const unsigned char kData[] = {12, 11, 99}; - mem2 = MakeRefCounted<RefCountedBytes>(kData, std::size(kData)); + const uint8_t kData[] = {12, 11, 99}; + mem2 = MakeRefCounted<RefCountedBytes>(base::span(kData)); } - ASSERT_EQ(3U, mem2->size()); - EXPECT_EQ(12U, mem2->front()[0]); - EXPECT_EQ(11U, mem2->front()[1]); - EXPECT_EQ(99U, mem2->front()[2]); - ConvertToByteSpanAndCheckSize(*mem2, 3); + EXPECT_THAT(base::span(*mem2), ElementsAre(12, 11, 99)); } TEST(RefCountedMemoryUnitTest, RefCountedBytesMutable) { auto mem = MakeRefCounted<RefCountedBytes>(10); - ASSERT_EQ(10U, mem->size()); - EXPECT_THAT(mem->data(), Each(0U)); + EXPECT_THAT(base::span(*mem), ElementsAre(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - // Test non-const versions of data(), front() and front_as<>(). - mem->data()[0] = 1; - mem->front()[1] = 2; - mem->front_as<char>()[2] = 3; + // Test non-const version of as_vector(). + mem->as_vector()[1u] = 1; - EXPECT_THAT(mem->data(), ElementsAre(1, 2, 3, 0, 0, 0, 0, 0, 0, 0)); + EXPECT_THAT(base::span(*mem), ElementsAre(0, 1, 0, 0, 0, 0, 0, 0, 0, 0)); } TEST(RefCountedMemoryUnitTest, RefCountedString) { scoped_refptr<RefCountedMemory> mem = base::MakeRefCounted<base::RefCountedString>(std::string("destroy me")); - ASSERT_EQ(10U, mem->size()); - EXPECT_EQ('d', mem->front()[0]); - EXPECT_EQ('e', mem->front()[1]); - EXPECT_EQ('e', mem->front()[9]); - - ConvertToByteSpanAndCheckSize(*mem, 10); + EXPECT_EQ(base::span(*mem), base::span_from_cstring("destroy me")); } TEST(RefCountedMemoryUnitTest, Equals) { scoped_refptr<RefCountedMemory> mem1 = base::MakeRefCounted<base::RefCountedString>(std::string("same")); - std::vector<unsigned char> d2 = {'s', 'a', 'm', 'e'}; + std::vector<uint8_t> d2 = {'s', 'a', 'm', 'e'}; scoped_refptr<RefCountedMemory> mem2 = RefCountedBytes::TakeVector(&d2); EXPECT_TRUE(mem1->Equals(mem2));
diff --git a/base/strings/cstring_view_nocompile.nc b/base/strings/cstring_view_nocompile.nc index 690fb8a..6cffcf9 100644 --- a/base/strings/cstring_view_nocompile.nc +++ b/base/strings/cstring_view_nocompile.nc
@@ -7,6 +7,8 @@ #include "base/strings/cstring_view.h" +#include <vector> + namespace base { namespace {
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index 45fb1941..59160e01 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
@@ -573,13 +573,14 @@ #endif // BUILDFLAG(IS_WIN) if (main_thread_only().task_source->OnIdle()) { + work_id_provider_->IncrementWorkId(); // The OnIdle() callback resulted in more immediate work, so schedule a // DoWork callback. For some message pumps returning true from here is // sufficient to do that but not on mac. pump_->ScheduleWork(); return false; } - + work_id_provider_->IncrementWorkId(); // This is mostly redundant with the identical call in BeforeWait (upcoming) // but some uninstrumented MessagePump impls don't call BeforeWait so it must // also be done here.
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc index a9235ca..17673f3 100644 --- a/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc +++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl_unittest.cc
@@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" +#include "base/message_loop/message_pump.h" #include "base/task/sequence_manager/task_queue.h" #include "base/task/sequence_manager/thread_controller_power_monitor.h" #include "base/task/single_thread_task_runner.h" @@ -2094,4 +2095,140 @@ RunLoop().Run(); } +TEST_F(ThreadControllerWithMessagePumpNoBatchesTest, + WorkIdIncrementedForEveryWorkItem) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + // Each task will increment work id by 2, once on begin work and another + // on end work. + delegate->DoWork(); + EXPECT_EQ(work_id_provider->GetWorkId(), 2u); + delegate->DoWork(); + EXPECT_EQ(work_id_provider->GetWorkId(), 4u); + }); + + for (int task_count = 0; task_count < 2; task_count++) { + task_source_.AddTask(FROM_HERE, DoNothing(), TimeTicks()); + } + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); +} + +TEST_F(ThreadControllerWithMessagePumpTest, + WorkIdIncrementedForEveryWorkItemInBatches) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + thread_controller_.SetWorkBatchSize(2); + + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + delegate->DoWork(); + // Each task will increment work id by 2, once on begin work and another + // on end work. + EXPECT_EQ(work_id_provider->GetWorkId(), 4u); + }); + + for (int task_count = 0; task_count < 2; task_count++) { + task_source_.AddTask(FROM_HERE, DoNothing(), TimeTicks()); + } + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); +} + +TEST_F(ThreadControllerWithMessagePumpTest, WorkIdIncrementedForIdleWork) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + delegate->DoIdleWork(); + EXPECT_EQ(work_id_provider->GetWorkId(), 1u); + }); + + task_source_.AddTask(FROM_HERE, DoNothing()); + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); +} + +TEST_F(ThreadControllerWithMessagePumpTest, WorkIdIncrementedScopedDoWorkItem) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + MessagePump::Delegate::ScopedDoWorkItem scoped_do_work_item = + delegate->BeginWorkItem(); + // ScopedDoWorkItem will increment work id by 1 on construction and + // another on destruction. + EXPECT_EQ(work_id_provider->GetWorkId(), 1u); + }); + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); + // Delegate::Run() itself will increment work id to account for pump overhead. + EXPECT_EQ(work_id_provider->GetWorkId(), 3u); +} + +TEST_F(ThreadControllerWithMessagePumpTest, + WorkIdIncrementedDelegateBeforeWait) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + // Delegate::BeforeWait will increment work id by 1 before waiting for + // work. + delegate->BeforeWait(); + EXPECT_EQ(work_id_provider->GetWorkId(), 1u); + }); + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); +} + +TEST_F(ThreadControllerWithMessagePumpTest, WorkIdIncrementedDelegateRun) { + SingleThreadTaskRunner::CurrentDefaultHandle handle( + MakeRefCounted<FakeTaskRunner>()); + WorkIdProvider* work_id_provider = WorkIdProvider::GetForCurrentThread(); + + work_id_provider->SetCurrentWorkIdForTesting(0u); + + EXPECT_CALL(*message_pump_, Run(_)) + .WillOnce([&](MessagePump::Delegate* delegate) { + EXPECT_EQ(work_id_provider->GetWorkId(), 0u); + }); + + RunLoop run_loop; + run_loop.Run(); + testing::Mock::VerifyAndClearExpectations(message_pump_); + // Delegate::Run() itself will increment work id to account for pump overhead. + EXPECT_EQ(work_id_provider->GetWorkId(), 1u); +} + } // namespace base::sequence_manager::internal
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc index 7f3ac459..ca34d905 100644 --- a/base/test/trace_event_analyzer.cc +++ b/base/test/trace_event_analyzer.cc
@@ -28,7 +28,7 @@ base::trace_event::TraceResultBuffer* buffer, const scoped_refptr<base::RefCountedString>& json, bool has_more_events) { - buffer->AddFragment(json->data()); + buffer->AddFragment(json->as_string()); if (!has_more_events) std::move(quit_closure).Run(); }
diff --git a/base/test/trace_event_analyzer_unittest.cc b/base/test/trace_event_analyzer_unittest.cc index e6b08ba2..929cabf 100644 --- a/base/test/trace_event_analyzer_unittest.cc +++ b/base/test/trace_event_analyzer_unittest.cc
@@ -46,7 +46,7 @@ base::WaitableEvent* flush_complete_event, const scoped_refptr<base::RefCountedString>& json_events_str, bool has_more_events) { - buffer_.AddFragment(json_events_str->data()); + buffer_.AddFragment(json_events_str->as_string()); if (!has_more_events) flush_complete_event->Signal(); }
diff --git a/base/test/trace_to_file.cc b/base/test/trace_to_file.cc index da2fb76..f271596 100644 --- a/base/test/trace_to_file.cc +++ b/base/test/trace_to_file.cc
@@ -79,7 +79,7 @@ trace_event::TraceResultBuffer* buffer, const scoped_refptr<RefCountedString>& json_events_str, bool has_more_events) { - buffer->AddFragment(json_events_str->data()); + buffer->AddFragment(json_events_str->as_string()); if (!has_more_events) std::move(quit_closure).Run(); }
diff --git a/base/trace_event/trace_event_memory_overhead.cc b/base/trace_event/trace_event_memory_overhead.cc index 1ba4c5e..0c2dfc8 100644 --- a/base/trace_event/trace_event_memory_overhead.cc +++ b/base/trace_event/trace_event_memory_overhead.cc
@@ -91,7 +91,7 @@ void TraceEventMemoryOverhead::AddRefCountedString( const RefCountedString& str) { Add(kOther, sizeof(RefCountedString)); - AddString(str.data()); + AddString(str.as_string()); } void TraceEventMemoryOverhead::AddValue(const Value& value) {
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 5df0bed..c9711b9 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc
@@ -198,12 +198,12 @@ bool has_more_events) { num_flush_callbacks_++; if (num_flush_callbacks_ > 1) { - EXPECT_FALSE(events_str->data().empty()); + EXPECT_FALSE(events_str->as_string().empty()); } AutoLock lock(lock_); json_output_.json_output.clear(); trace_buffer_.Start(); - trace_buffer_.AddFragment(events_str->data()); + trace_buffer_.AddFragment(events_str->as_string()); trace_buffer_.Finish(); std::optional<Value> root = base::JSONReader::Read(
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index b80b33f..8465a63 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -372,7 +372,7 @@ TraceLog::OutputCallback flush_callback) : flush_task_runner_(flush_task_runner), flush_callback_(std::move(flush_callback)) { - buffer_->data().reserve(kBufferReserveCapacity); + buffer_->as_string().reserve(kBufferReserveCapacity); } ~JsonStringOutputWriter() override { Flush(/*has_more=*/false); } @@ -383,22 +383,22 @@ DCHECK_EQ(string, kJsonPrefix); did_strip_prefix_ = true; return perfetto::trace_processor::util::OkStatus(); - } else if (buffer_->data().empty() && + } else if (buffer_->as_string().empty() && !strncmp(string.c_str(), kJsonJoiner, strlen(kJsonJoiner))) { // We only remove the leading joiner comma for the first chunk in a buffer // since the consumer is expected to insert commas between the buffers we // provide. - buffer_->data() += string.substr(strlen(kJsonJoiner)); + buffer_->as_string() += string.substr(strlen(kJsonJoiner)); } else if (!strncmp(string.c_str(), kJsonSuffix, strlen(kJsonSuffix))) { return perfetto::trace_processor::util::OkStatus(); } else { - buffer_->data() += string; + buffer_->as_string() += string; } - if (buffer_->data().size() > kBufferLimitInBytes) { + if (buffer_->as_string().size() > kBufferLimitInBytes) { Flush(/*has_more=*/true); // Reset the buffer_ after moving it above. buffer_ = new RefCountedString(); - buffer_->data().reserve(kBufferReserveCapacity); + buffer_->as_string().reserve(kBufferReserveCapacity); } return perfetto::trace_processor::util::OkStatus(); } @@ -1384,7 +1384,7 @@ if (proto_output_callback_) { scoped_refptr<RefCountedString> chunk = new RefCountedString(); if (size) - chunk->data().assign(data, size); + chunk->as_string().assign(data, size); proto_output_callback_.Run(std::move(chunk), has_more); if (!has_more) { proto_output_callback_.Reset(); @@ -1424,18 +1424,18 @@ // to let the caller know the completion of flush. scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString(); const size_t kReserveCapacity = kTraceEventBufferSizeInBytes * 5 / 4; - json_events_str_ptr->data().reserve(kReserveCapacity); + json_events_str_ptr->as_string().reserve(kReserveCapacity); while (const TraceBufferChunk* chunk = logged_events->NextChunk()) { for (size_t j = 0; j < chunk->size(); ++j) { size_t size = json_events_str_ptr->size(); if (size > kTraceEventBufferSizeInBytes) { flush_output_callback.Run(json_events_str_ptr, true); json_events_str_ptr = new RefCountedString(); - json_events_str_ptr->data().reserve(kReserveCapacity); + json_events_str_ptr->as_string().reserve(kReserveCapacity); } else if (size) { - json_events_str_ptr->data().append(",\n"); + json_events_str_ptr->as_string().append(",\n"); } - chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()), + chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->as_string()), argument_filter_predicate); } }
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto index 29a4cb3e3..27ab22b 100644 --- a/base/tracing/protos/chrome_track_event.proto +++ b/base/tracing/protos/chrome_track_event.proto
@@ -39,6 +39,7 @@ TASK_SCOPE_SCHEDULER_POST_TASK = 6; TASK_SCOPE_REQUEST_IDLE_CALLBACK = 7; TASK_SCOPE_XML_HTTP_REQUEST = 8; + TASK_SCOPE_SOFT_NAVIGATION = 9; } optional TaskScopeType type = 1; optional int64 scope_task_id = 2;
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc index 4e25e466..a30a932a 100644 --- a/cc/paint/discardable_image_map.cc +++ b/cc/paint/discardable_image_map.cc
@@ -12,7 +12,7 @@ #include "base/auto_reset.h" #include "base/check.h" #include "base/containers/adapters.h" -#include "base/memory/raw_ptr.h" +#include "base/memory/stack_allocated.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/sequence_checker.h" @@ -28,61 +28,38 @@ #include "ui/gfx/geometry/skia_conversions.h" namespace cc { -namespace { -const int kMaxRectsSize = 256; -class DiscardableImageGenerator { +class DiscardableImageMap::Generator { + STACK_ALLOCATED(); + public: - DiscardableImageGenerator(int width, - int height, - const PaintOpBuffer& buffer) { - SkNoDrawCanvas canvas(width, height); - GatherDiscardableImages(buffer, nullptr, &canvas); + Generator(DiscardableImageMap& map, + SkNoDrawCanvas& canvas, + const PaintOpBuffer& buffer) + : map_(map), canvas_(canvas) { + GatherDiscardableImages(buffer, nullptr); } - ~DiscardableImageGenerator() = default; - - std::vector<std::pair<DrawImage, gfx::Rect>> TakeImages() { - return std::move(image_set_); - } - base::flat_map<PaintImage::Id, DiscardableImageMap::Rects> - TakeImageIdToRectsMap() { - return std::move(image_id_to_rects_); - } - base::flat_map<PaintImage::Id, PaintImage::DecodingMode> - TakeDecodingModeMap() { - return std::move(decoding_mode_map_); - } - std::vector<DiscardableImageMap::AnimatedImageMetadata> - TakeAnimatedImagesMetadata() { - return std::move(animated_images_metadata_); - } - std::vector<DiscardableImageMap::PaintWorkletInputWithImageId> - TakePaintWorkletInputs() { - return std::move(paint_worklet_inputs_); - } - - gfx::ContentColorUsage content_color_usage() const { - return content_color_usage_; - } - bool contains_hbd_images() const { return contains_hbd_images_; } private: + static constexpr int kMaxRectsSize = 256; + class ImageGatheringProvider : public ImageProvider { + STACK_ALLOCATED(); + public: - ImageGatheringProvider(DiscardableImageGenerator* generator, - const gfx::Rect& op_rect) + ImageGatheringProvider(Generator& generator, const gfx::Rect& op_rect) : generator_(generator), op_rect_(op_rect) {} ~ImageGatheringProvider() override = default; ScopedResult GetRasterContent(const DrawImage& draw_image) override { - generator_->AddImage(draw_image.paint_image(), false, - SkRect::Make(draw_image.src_rect()), op_rect_, - SkM44(), draw_image.filter_quality()); + generator_.AddImage(draw_image.paint_image(), false, + SkRect::Make(draw_image.src_rect()), op_rect_, + SkM44(), draw_image.filter_quality()); return ScopedResult(); } private: - raw_ptr<DiscardableImageGenerator> generator_; + Generator& generator_; gfx::Rect op_rect_; }; @@ -94,43 +71,39 @@ // |top_level_op_rect| will be used as the rect for tracking the position of // this image in the top-level buffer. void GatherDiscardableImages(const PaintOpBuffer& buffer, - const gfx::Rect* top_level_op_rect, - SkNoDrawCanvas* canvas) { + const gfx::Rect* top_level_op_rect) { if (!buffer.HasDiscardableImages()) return; // Prevent PaintOpBuffers from having side effects back into the canvas. - SkAutoCanvasRestore save_restore(canvas, true); + SkAutoCanvasRestore save_restore(&canvas_, true); - PlaybackParams params(nullptr, canvas->getLocalToDevice()); + PlaybackParams params(nullptr, canvas_.getLocalToDevice()); // TODO(khushalsagar): Optimize out save/restore blocks if there are no // images in the draw ops between them. for (const PaintOp& op : buffer) { // We need to play non-draw ops on the SkCanvas since they can affect the // transform/clip state. if (!op.IsDrawOp()) - op.Raster(canvas, params); + op.Raster(&canvas_, params); if (!PaintOp::OpHasDiscardableImages(op)) continue; gfx::Rect op_rect; - std::optional<gfx::Rect> local_op_rect; - if (top_level_op_rect) { op_rect = *top_level_op_rect; } else { - const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds()); - const SkMatrix& ctm = canvas->getTotalMatrix(); + const SkRect& clip_rect = SkRect::Make(canvas_.getDeviceClipBounds()); + const SkMatrix& ctm = canvas_.getTotalMatrix(); - local_op_rect = PaintOp::ComputePaintRect(op, clip_rect, ctm); - if (local_op_rect.value().IsEmpty()) - continue; - - op_rect = local_op_rect.value(); + op_rect = PaintOp::ComputePaintRect(op, clip_rect, ctm); + } + if (op_rect.IsEmpty()) { + continue; } - const SkM44& ctm = canvas->getLocalToDevice(); + const SkM44& ctm = canvas_.getLocalToDevice(); if (op.IsPaintOpWithFlags()) { AddImageFromFlags(op_rect, static_cast<const PaintOpWithFlags&>(op).flags, ctm); @@ -191,7 +164,7 @@ } else if (op_type == PaintOpType::kDrawRecord) { GatherDiscardableImages( static_cast<const DrawRecordOp&>(op).record.buffer(), - top_level_op_rect, canvas); + top_level_op_rect); } } } @@ -239,17 +212,16 @@ scaled_tile_rect.height()); canvas.setMatrix(SkMatrix::RectToRect(shader->tile(), scaled_tile_rect)); base::AutoReset<bool> auto_reset(&only_gather_animated_images_, true); - size_t prev_image_set_size = image_set_.size(); - GatherDiscardableImages(shader->paint_record()->buffer(), &op_rect, - &canvas); + size_t prev_images_size = map_.images_.size(); + GatherDiscardableImages(shader->paint_record()->buffer(), &op_rect); // We only track animated images for PaintShaders. If we added any entry - // to the |image_set_|, this shader any has animated images. + // to the |map_.images_|, this shader any has animated images. // Note that it is thread-safe to set the |has_animated_images| bit on // PaintShader here since the analysis is done on the main thread, before // the PaintOpBuffer is used for rasterization. - DCHECK_GE(image_set_.size(), prev_image_set_size); - const bool has_animated_images = image_set_.size() > prev_image_set_size; + DCHECK_GE(map_.images_.size(), prev_images_size); + const bool has_animated_images = map_.images_.size() > prev_images_size; const_cast<PaintShader*>(shader)->set_has_animated_images( has_animated_images); } @@ -264,12 +236,12 @@ } base::AutoReset<bool> auto_reset(&only_gather_animated_images_, true); - size_t prev_image_set_size = image_set_.size(); - ImageGatheringProvider image_provider(this, op_rect); + size_t prev_images_size = map_.images_.size(); + ImageGatheringProvider image_provider(*this, op_rect); filter->SnapshotWithImages(&image_provider); - DCHECK_GE(image_set_.size(), prev_image_set_size); - const bool has_animated_images = image_set_.size() > prev_image_set_size; + DCHECK_GE(map_.images_.size(), prev_images_size); + const bool has_animated_images = map_.images_.size() > prev_images_size; const_cast<PaintFilter*>(filter)->set_has_animated_images( has_animated_images); } @@ -287,17 +259,19 @@ src_rect.roundOut(&src_irect); if (paint_image.IsPaintWorklet()) { - paint_worklet_inputs_.push_back(std::make_pair( - paint_image.paint_worklet_input(), paint_image.stable_id())); + map_.paint_worklet_inputs_.emplace_back( + paint_image.paint_worklet_input(), paint_image.stable_id()); } else { const auto image_color_usage = paint_image.GetContentColorUsage(); - content_color_usage_ = std::max(content_color_usage_, image_color_usage); + map_.content_color_usage_ = + std::max(map_.content_color_usage_, image_color_usage); - if (paint_image.is_high_bit_depth()) - contains_hbd_images_ = true; + if (paint_image.is_high_bit_depth()) { + map_.contains_hbd_images_ = true; + } } - auto& rects = image_id_to_rects_[paint_image.stable_id()]; + auto& rects = map_.image_id_to_rects_[paint_image.stable_id()]; if (rects.size() >= kMaxRectsSize) { rects.back().Union(image_rect); } else { @@ -305,11 +279,12 @@ } if (paint_image.IsLazyGenerated()) { - auto decoding_mode_it = decoding_mode_map_.find(paint_image.stable_id()); + auto decoding_mode_it = + map_.decoding_mode_map_.find(paint_image.stable_id()); // Use the decoding mode if we don't have one yet, otherwise use the more // conservative one of the two existing ones. - if (decoding_mode_it == decoding_mode_map_.end()) { - decoding_mode_map_[paint_image.stable_id()] = + if (decoding_mode_it == map_.decoding_mode_map_.end()) { + map_.decoding_mode_map_[paint_image.stable_id()] = paint_image.decoding_mode(); } else { decoding_mode_it->second = PaintImage::GetConservative( @@ -318,7 +293,7 @@ } if (paint_image.ShouldAnimate()) { - animated_images_metadata_.emplace_back( + map_.animated_images_metadata_.emplace_back( paint_image.stable_id(), paint_image.completion_state(), paint_image.GetFrameMetadata(), paint_image.repetition_count(), paint_image.reset_animation_sequence_id()); @@ -328,7 +303,7 @@ if (paint_image.IsPaintWorklet()) { // PaintWorklet-backed images don't go through the image decode pipeline // (they are painted pre-raster from LayerTreeHostImpl), so do not need to - // be added to the |image_set_|. + // be added to the |map_.images_|. add_image = false; } else if (only_gather_animated_images_) { // If we are iterating images in a record shader, only track them if they @@ -339,27 +314,16 @@ } if (add_image) { - image_set_.emplace_back(DrawImage(std::move(paint_image), use_dark_mode, - src_irect, filter_quality, matrix), - image_rect); + map_.images_.emplace_back(DrawImage(std::move(paint_image), use_dark_mode, + src_irect, filter_quality, matrix), + image_rect); } } - std::vector<std::pair<DrawImage, gfx::Rect>> image_set_; - base::flat_map<PaintImage::Id, DiscardableImageMap::Rects> image_id_to_rects_; - std::vector<DiscardableImageMap::AnimatedImageMetadata> - animated_images_metadata_; - std::vector<DiscardableImageMap::PaintWorkletInputWithImageId> - paint_worklet_inputs_; - PaintImageIdFlatSet paint_worklet_image_ids_; - base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map_; + DiscardableImageMap& map_; + SkNoDrawCanvas& canvas_; bool only_gather_animated_images_ = false; - - gfx::ContentColorUsage content_color_usage_ = gfx::ContentColorUsage::kSRGB; - bool contains_hbd_images_ = false; -}; - -} // namespace +}; // DiscardableImageMap::Generator DiscardableImageMap::DiscardableImageMap() { DETACH_FROM_SEQUENCE(images_rtree_sequence_checker_); @@ -374,15 +338,8 @@ return; } - DiscardableImageGenerator generator(bounds.right(), bounds.bottom(), - paint_op_buffer); - image_id_to_rects_ = generator.TakeImageIdToRectsMap(); - images_ = generator.TakeImages(); - animated_images_metadata_ = generator.TakeAnimatedImagesMetadata(); - paint_worklet_inputs_ = generator.TakePaintWorkletInputs(); - decoding_mode_map_ = generator.TakeDecodingModeMap(); - contains_hbd_images_ = generator.contains_hbd_images(); - content_color_usage_ = generator.content_color_usage(); + SkNoDrawCanvas canvas(bounds.right(), bounds.bottom()); + Generator generator(*this, canvas, paint_op_buffer); DCHECK_CALLED_ON_VALID_SEQUENCE(images_rtree_sequence_checker_); CHECK(!images_rtree_); DETACH_FROM_SEQUENCE(images_rtree_sequence_checker_);
diff --git a/cc/paint/discardable_image_map.h b/cc/paint/discardable_image_map.h index afda313a..6eaefb02 100644 --- a/cc/paint/discardable_image_map.h +++ b/cc/paint/discardable_image_map.h
@@ -28,7 +28,7 @@ #include "ui/gfx/geometry/size.h" namespace cc { -class DiscardableImageStore; + class PaintOpBuffer; // This class is used for generating discardable images data (see DrawImage @@ -85,14 +85,8 @@ } private: - friend class ScopedMetadataGenerator; friend class DiscardableImageMapTest; - - std::unique_ptr<DiscardableImageStore> BeginGeneratingMetadata( - const gfx::Size& bounds); - void EndGeneratingMetadata( - std::vector<std::pair<DrawImage, gfx::Rect>> images, - base::flat_map<PaintImage::Id, gfx::Rect> image_id_to_rect); + class Generator; base::flat_map<PaintImage::Id, Rects> image_id_to_rects_; std::vector<AnimatedImageMetadata> animated_images_metadata_;
diff --git a/cc/paint/skottie_text_property_value.h b/cc/paint/skottie_text_property_value.h index e18d47d..bfb9b34 100644 --- a/cc/paint/skottie_text_property_value.h +++ b/cc/paint/skottie_text_property_value.h
@@ -36,7 +36,7 @@ bool operator!=(const SkottieTextPropertyValue& other) const; void SetText(std::string text); - const std::string& text() const { return text_->data(); } + const std::string& text() const { return text_->as_string(); } void set_box(gfx::RectF box) { box_ = std::move(box); } const gfx::RectF& box() const { return box_; }
diff --git a/chrome/VERSION b/chrome/VERSION index faf575a..9f379640 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=126 MINOR=0 -BUILD=6427 +BUILD=6428 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index e654d1b..ad4ec69f 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -383,7 +383,6 @@ "//chrome/browser/creator/android:java", "//chrome/browser/data_sharing:factory_java", "//chrome/browser/data_sharing:java", - "//chrome/browser/data_sharing/android:java", "//chrome/browser/dependency_injection:java", "//chrome/browser/device:java", "//chrome/browser/device_reauth/android:java", @@ -857,7 +856,7 @@ "//chrome/browser/android/content:java", "//chrome/browser/android/httpclient:java", "//chrome/browser/commerce/merchant_viewer/android:java", - "//chrome/browser/data_sharing/android:java", + "//chrome/browser/data_sharing:java", "//chrome/browser/download/internal/android:java", "//chrome/browser/facilitated_payments/ui/android/internal:java", "//chrome/browser/hub/internal:java", @@ -1172,6 +1171,7 @@ "//chrome/browser/ui/android/plus_addresses:junit", "//chrome/browser/ui/android/quickactionsearchwidget:java", "//chrome/browser/ui/android/searchactivityutils:java", + "//chrome/browser/ui/android/searchactivityutils:junit", "//chrome/browser/ui/android/signin:java", "//chrome/browser/ui/android/signin:junit", "//chrome/browser/ui/android/theme:java", @@ -2878,7 +2878,6 @@ "//chrome/browser/ui/android/night_mode:unit_device_javatests", "//chrome/browser/ui/android/omnibox:unit_device_javatests", "//chrome/browser/ui/android/page_insights:unit_device_javatests", - "//chrome/browser/ui/android/searchactivityutils:unit_device_javatests", "//chrome/browser/ui/android/signin:unit_device_javatests", "//chrome/browser/ui/messages/android:unit_device_javatests", "//components/browser_ui/accessibility/android:unit_device_javatests",
diff --git a/chrome/android/baseline_profiles/profile.txt b/chrome/android/baseline_profiles/profile.txt index d524aba..ae3b2f2 100644 --- a/chrome/android/baseline_profiles/profile.txt +++ b/chrome/android/baseline_profiles/profile.txt
@@ -3959,7 +3959,6 @@ HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->finishNativeInitialization()V HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->getCurrentSmallestScreenWidth(Landroid/content/Context;)I HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->isActivityFinishingOrDestroyed()Z -HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->isInstantStartEnabled()Z HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->maybePreconnect()V HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->onAttachedToWindow()V HSPLorg/chromium/chrome/browser/init/AsyncInitializationActivity;->onCreate(Landroid/os/Bundle;)V @@ -6306,7 +6305,6 @@ HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities;->isTabToGtsAnimationEnabled()Z HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities;->isTabletGridTabSwitcherEnabled(Landroid/content/Context;)Z HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities;->isTabletGridTabSwitcherPolishEnabled(Landroid/content/Context;)Z -HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities;->supportInstantStart(Landroid/content/Context;Z)Z Lorg/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider; HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider;->getTabGridDialogUngroupBarBackgroundColor(Landroid/content/Context;ZZ)I HSPLorg/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider;->getTabGridDialogUngroupBarTextColor(Landroid/content/Context;ZZ)I
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 2546137a..a5f3e21 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -135,6 +135,7 @@ "java/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialog.java", "java/src/org/chromium/chrome/browser/autofill/settings/AutofillDeleteSavedCvcsConfirmationDialog.java", "java/src/org/chromium/chrome/browser/autofill/settings/AutofillEditLinkPreference.java", + "java/src/org/chromium/chrome/browser/autofill/settings/AutofillIbanEditor.java", "java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java", "java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java", "java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsDelegate.java", @@ -1130,6 +1131,7 @@ "java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java", "java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaver.java", "java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java", + "java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java", "java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java", "java/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorController.java", "java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 0b7dd96..2c5ed38f 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -345,6 +345,7 @@ "junit/src/org/chromium/chrome/browser/tab/TabViewManagerUnitTest.java", "junit/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserverUnitTest.java", "junit/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplUnitTest.java", + "junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java", "junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java", "junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerUnitTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/ArchivedTabModelSelectorImplTest.java",
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml index 694c45d..77ea1909 100644 --- a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml +++ b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
@@ -72,17 +72,6 @@ android:layout_height="56dp" android:layout_marginStart="4dp" android:visibility="gone"/> - <org.chromium.ui.widget.ButtonCompat - android:id="@+id/create_group_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:layout_centerHorizontal="true" - android:layout_margin="8dp" - android:elevation="4dp" - android:text="@string/tabswitcher_create_group" - android:visibility="gone" - style="@style/FilledButton"/> </RelativeLayout> <org.chromium.ui.widget.ChromeImageView android:id="@+id/action_button"
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java index e755499d..3fbefb22 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -270,7 +270,7 @@ } private View.OnClickListener getColorIconClickListener() { - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { return (view) -> { showColorPickerPopup(view); TabUiMetricsHelper.recordTabGroupColorChangeActionMetrics(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java index ce498d8..534a466d 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java
@@ -161,7 +161,7 @@ R.style.TextAppearance_TextLarge_Primary_Baseline_Light, isIncognito, true)); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { itemList.add( BrowserUiListMenuUtils.buildMenuListItemWithIncognitoText( R.string.tab_grid_dialog_toolbar_edit_group_color,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinder.java index 1897b1ac..a2558e9 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewBinder.java
@@ -133,7 +133,7 @@ ViewUtils.requestLayout(viewHolder.contentView, "TabGridDialogViewBinder.bind"); } } else if (PRIMARY_COLOR == propertyKey) { - viewHolder.toolbarView.setPrimaryColor(model.get(PRIMARY_COLOR)); + viewHolder.toolbarView.setContentBackgroundColor(model.get(PRIMARY_COLOR)); viewHolder.contentView.setBackgroundColor(model.get(PRIMARY_COLOR)); } else if (TINT == propertyKey) { if (model.get(TINT) != null) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java index 779ed34..f5b7874 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
@@ -31,7 +31,6 @@ import org.chromium.chrome.tab_ui.R; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; -import org.chromium.ui.widget.ButtonCompat; import org.chromium.ui.widget.ChromeImageView; import org.chromium.ui.widget.ViewLookupCachingFrameLayout; @@ -158,22 +157,6 @@ model.get(TabProperties.TAB_SELECTED_LISTENER).run(tabId); }); } - } else if (TabProperties.CREATE_GROUP_LISTENER == propertyKey) { - TabListMediator.TabActionListener listener = - model.get(TabProperties.CREATE_GROUP_LISTENER); - ButtonCompat createGroupButton = - (ButtonCompat) view.fastFindViewById(R.id.create_group_button); - if (listener == null) { - createGroupButton.setVisibility(View.GONE); - createGroupButton.setOnClickListener(null); - return; - } - createGroupButton.setVisibility(View.VISIBLE); - createGroupButton.setOnClickListener( - v -> { - int tabId = model.get(TabProperties.TAB_ID); - listener.run(tabId); - }); } else if (CARD_ALPHA == propertyKey) { view.setAlpha(model.get(CARD_ALPHA)); } else if (TabProperties.IPH_PROVIDER == propertyKey) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index 1443a42..134808b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -8,7 +8,9 @@ import android.os.Handler; import android.view.View; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; import org.chromium.base.CallbackController; @@ -38,6 +40,7 @@ import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator.BottomControlsVisibilityController; import org.chromium.chrome.tab_ui.R; +import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.LoadUrlParams; @@ -111,6 +114,8 @@ private Callback<Boolean> mOmniboxFocusObserver; private boolean mIsTabGroupUiVisible; private boolean mIsShowingOverViewMode; + private final @ColorInt int mPrimaryBackgroundColor; + private final @ColorInt int mIncognitoBackgroundColor; TabGroupUiMediator( Context context, @@ -125,6 +130,37 @@ LazyOneshotSupplier<TabGridDialogMediator.DialogController> dialogControllerSupplier, ObservableSupplier<Boolean> omniboxFocusStateSupplier) { + this( + context, + visibilityController, + resetHandler, + model, + tabModelSelector, + tabCreatorManager, + layoutStateProviderSupplier, + incognitoStateProvider, + dialogControllerSupplier, + omniboxFocusStateSupplier, + SemanticColorUtils.getDialogBgColor(context), + context.getColor(org.chromium.chrome.R.color.dialog_bg_color_dark_baseline)); + } + + @VisibleForTesting + TabGroupUiMediator( + Context context, + BottomControlsVisibilityController visibilityController, + ResetHandler resetHandler, + PropertyModel model, + TabModelSelector tabModelSelector, + TabCreatorManager tabCreatorManager, + OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier, + IncognitoStateProvider incognitoStateProvider, + @Nullable + LazyOneshotSupplier<TabGridDialogMediator.DialogController> + dialogControllerSupplier, + ObservableSupplier<Boolean> omniboxFocusStateSupplier, + @ColorInt int primaryBackgroundColor, + @ColorInt int incognitoBackgroundColor) { mContext = context; mResetHandler = resetHandler; mModel = model; @@ -134,6 +170,8 @@ mIncognitoStateProvider = incognitoStateProvider; mTabGridDialogControllerSupplier = dialogControllerSupplier; mOmniboxFocusStateSupplier = omniboxFocusStateSupplier; + mPrimaryBackgroundColor = primaryBackgroundColor; + mIncognitoBackgroundColor = incognitoBackgroundColor; if (layoutStateProviderSupplier.get() != null && (layoutStateProviderSupplier.get().isLayoutVisible(LayoutType.TAB_SWITCHER) @@ -317,6 +355,7 @@ mIncognitoStateObserver = (isIncognito) -> { mModel.set(TabGroupUiProperties.IS_INCOGNITO, isIncognito); + setBottomControlsBackgroundColor(isIncognito); }; filterProvider.addTabModelFilterObserver(mTabModelObserver); @@ -349,6 +388,13 @@ } } + private void setBottomControlsBackgroundColor(boolean isIncognito) { + @ColorInt + int backgroundColor = isIncognito ? mIncognitoBackgroundColor : mPrimaryBackgroundColor; + mVisibilityController.setBottomControlsColor(backgroundColor); + mModel.set(TabGroupUiProperties.BACKGROUND_COLOR, backgroundColor); + } + void setupLeftButtonDrawable(int drawableId) { mModel.set(TabGroupUiProperties.LEFT_BUTTON_DRAWABLE_ID, drawableId); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java index 724127a6..bea05f6a 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java
@@ -21,6 +21,8 @@ new PropertyModel.WritableBooleanPropertyKey(); public static final PropertyModel.WritableIntPropertyKey LEFT_BUTTON_DRAWABLE_ID = new PropertyModel.WritableIntPropertyKey(); + public static final PropertyModel.WritableIntPropertyKey BACKGROUND_COLOR = + new PropertyModel.WritableIntPropertyKey(); /** * Integer, but not {@link PropertyModel.WritableIntPropertyKey} so that we can force update on @@ -41,6 +43,7 @@ IS_MAIN_CONTENT_VISIBLE, IS_INCOGNITO, LEFT_BUTTON_DRAWABLE_ID, + BACKGROUND_COLOR, INITIAL_SCROLL_INDEX, LEFT_BUTTON_CONTENT_DESCRIPTION, RIGHT_BUTTON_CONTENT_DESCRIPTION
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java index 3aa59276..5034eab 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
@@ -29,7 +29,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.tab_ui.R; -import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.tab_groups.TabGroupColorId; import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.widget.ChromeImageView; @@ -160,13 +159,6 @@ } void setIsIncognito(boolean isIncognito) { - @ColorInt - int primaryColor = - isIncognito - ? getContext().getColor(R.color.dialog_bg_color_dark_baseline) - : SemanticColorUtils.getDialogBgColor(getContext()); - setPrimaryColor(primaryColor); - @ColorRes int tintListRes = isIncognito @@ -176,7 +168,7 @@ setTint(tintList); } - void setPrimaryColor(int color) { + void setContentBackgroundColor(int color) { mMainContent.setBackgroundColor(color); if (mFadingEdgeStart == null || mFadingEdgeEnd == null) return; mFadingEdgeStart.setColorFilter(color, PorterDuff.Mode.SRC_IN);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java index 895b56e5..12691eec 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tasks.tab_management; +import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.BACKGROUND_COLOR; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.INITIAL_SCROLL_INDEX; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.IS_INCOGNITO; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.IS_MAIN_CONTENT_VISIBLE; @@ -54,6 +55,8 @@ viewHolder.toolbarView.setIsIncognito(model.get(IS_INCOGNITO)); } else if (LEFT_BUTTON_DRAWABLE_ID == propertyKey) { viewHolder.toolbarView.setLeftButtonDrawableId(model.get(LEFT_BUTTON_DRAWABLE_ID)); + } else if (BACKGROUND_COLOR == propertyKey) { + viewHolder.toolbarView.setContentBackgroundColor(model.get(BACKGROUND_COLOR)); } else if (INITIAL_SCROLL_INDEX == propertyKey) { int index = (Integer) model.get(INITIAL_SCROLL_INDEX); LinearLayoutManager manager =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 83cc64fd..d283a33 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -845,6 +845,7 @@ mActionsOnAllRelatedTabs = actionOnRelatedTabs; mUiType = uiType; mPriceWelcomeMessageControllerSupplier = priceWelcomeMessageControllerSupplier; + mProfile = regularTabModelSupplier.get().getProfile(); mTabModelObserver = new TabModelObserver() {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java index 91be9bdf..dafcdd67 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
@@ -84,9 +84,6 @@ public static final WritableObjectPropertyKey<ColorStateList> CHECKED_DRAWABLE_STATE_LIST = new WritableObjectPropertyKey<>(); - public static final WritableObjectPropertyKey<TabListMediator.TabActionListener> - CREATE_GROUP_LISTENER = new WritableObjectPropertyKey<>(); - public static final PropertyModel.WritableIntPropertyKey CARD_ANIMATION_STATUS = new PropertyModel.WritableIntPropertyKey(); @@ -151,7 +148,6 @@ IPH_PROVIDER, TITLE, CHECKED_DRAWABLE_STATE_LIST, - CREATE_GROUP_LISTENER, CARD_ALPHA, CARD_ANIMATION_STATUS, SELECTABLE_TAB_CLICKED_LISTENER,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneCoordinatorFactoryUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneCoordinatorFactoryUnitTest.java index 0a740fa..466175f7 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneCoordinatorFactoryUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneCoordinatorFactoryUnitTest.java
@@ -106,6 +106,7 @@ mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE); when(mTabModelSelector.getTabModelFilterProvider()).thenReturn(mTabModelFilterProvider); + when(mTabModelSelector.getModel(false)).thenReturn(mTabModel); when(mTabModelFilterProvider.getTabModelFilter(false)).thenReturn(mTabModelFilter); when(mTabModelFilter.getTabModel()).thenReturn(mTabModel); when(mTabModel.getCount()).thenReturn(1);
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd index fe99a26b..5970ab6d 100644 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
@@ -218,9 +218,6 @@ </message> <!-- Tab Group Tab Switcher strings --> - <message name="IDS_TABSWITCHER_CREATE_GROUP" desc="This flat button is shown in the Tab Switcher, under an open tab. When the user taps the button, Chrome creates a new group of tabs that includes the existing tab. It's okay to use any of the following verbs in order to keep the text under 45 characters: Create, Make, Add."> - Create group - </message> <message name="IDS_ACCESSIBILITY_TAB_SWITCHER" desc="Accessibility string for Tab Switcher view. This string is announced when the Tab Switcher is shown to screen."> Tab Switcher </message>
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java index 6fbe264..0e22fb0 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java
@@ -11,6 +11,7 @@ import static org.junit.Assert.assertTrue; import android.content.res.ColorStateList; +import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; @@ -19,7 +20,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; -import androidx.annotation.ColorInt; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.test.annotation.UiThreadTest; @@ -77,7 +77,10 @@ new LinearLayoutManager( getActivity(), LinearLayoutManager.HORIZONTAL, false)); - mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS); + mModel = + new PropertyModel.Builder(TabGroupUiProperties.ALL_KEYS) + .with(TabGroupUiProperties.BACKGROUND_COLOR, Color.WHITE) + .build(); mMCP = PropertyModelChangeProcessor.create( mModel, @@ -161,12 +164,10 @@ @SmallTest public void testSetIncognito() { mModel.set(TabGroupUiProperties.IS_INCOGNITO, false); - @ColorInt int lightColor = ((ColorDrawable) mMainContent.getBackground()).getColor(); ColorStateList lightRightImageTint = mRightButton.getImageTintList(); ColorStateList lightLeftImageTint = mLeftButton.getImageTintList(); mModel.set(TabGroupUiProperties.IS_INCOGNITO, true); - assertNotEquals(lightColor, ((ColorDrawable) mMainContent.getBackground()).getColor()); assertNotEquals(lightRightImageTint, mLeftButton.getImageTintList()); assertNotEquals(lightLeftImageTint, mRightButton.getImageTintList()); } @@ -174,6 +175,17 @@ @Test @UiThreadTest @SmallTest + public void testSetBackgroundColor() { + mModel.set(TabGroupUiProperties.BACKGROUND_COLOR, Color.WHITE); + assertEquals(Color.WHITE, ((ColorDrawable) mMainContent.getBackground()).getColor()); + + mModel.set(TabGroupUiProperties.BACKGROUND_COLOR, Color.BLACK); + assertEquals(Color.BLACK, ((ColorDrawable) mMainContent.getBackground()).getColor()); + } + + @Test + @UiThreadTest + @SmallTest public void testSetLeftButtonContentDescription() { assertNull(mLeftButton.getContentDescription());
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java index e8e18d78..702b36d 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -102,7 +102,6 @@ import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.BlankUiTestActivityTestCase; -import org.chromium.ui.widget.ButtonCompat; import org.chromium.url.GURL; import java.lang.ref.WeakReference; @@ -836,40 +835,6 @@ @Test @MediumTest @UiThreadTest - public void testSetCreateGroupListener() { - ButtonCompat actionButton = mTabGridView.findViewById(R.id.create_group_button); - // By default, the create group button is invisible. - Assert.assertEquals(View.GONE, actionButton.getVisibility()); - - // When setup with actual listener, the button should be visible. - mGridModel.set(TabProperties.CREATE_GROUP_LISTENER, mMockCreateGroupButtonListener); - Assert.assertEquals(View.VISIBLE, actionButton.getVisibility()); - Assert.assertFalse(mCreateGroupButtonClicked.get()); - actionButton.performClick(); - Assert.assertTrue(mCreateGroupButtonClicked.get()); - mCreateGroupButtonClicked.set(false); - int firstCreateGroupId = mCreateGroupTabId.get(); - Assert.assertEquals(TAB1_ID, firstCreateGroupId); - - mGridModel.set(TabProperties.TAB_ID, TAB2_ID); - actionButton.performClick(); - Assert.assertTrue(mCreateGroupButtonClicked.get()); - mCreateGroupButtonClicked.set(false); - int secondCreateGroupId = mCreateGroupTabId.get(); - // When TAB_ID in PropertyModel is updated, binder should create group with updated tab ID. - Assert.assertEquals(TAB2_ID, secondCreateGroupId); - Assert.assertNotEquals(firstCreateGroupId, secondCreateGroupId); - - mGridModel.set(TabProperties.CREATE_GROUP_LISTENER, null); - actionButton.performClick(); - Assert.assertFalse(mCreateGroupButtonClicked.get()); - // When CREATE_GROUP_LISTENER is set to null, the button should be invisible. - Assert.assertEquals(View.GONE, actionButton.getVisibility()); - } - - @Test - @MediumTest - @UiThreadTest public void testPriceStringPriceDrop() { Tab tab = MockTab.createAndInitialize(1, mProfile); MockShoppingPersistedTabDataFetcher fetcher = new MockShoppingPersistedTabDataFetcher(tab);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java index 20f4027..f71f981 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -25,6 +25,7 @@ import android.content.Context; import android.content.res.Resources; +import android.graphics.Color; import android.view.View; import androidx.annotation.Nullable; @@ -90,6 +91,8 @@ private static final int TAB1_ROOT_ID = TAB1_ID; private static final int TAB2_ROOT_ID = TAB2_ID; private static final int TAB3_ROOT_ID = TAB2_ID; + private static final int PRIMARY_BACKGROUND_COLOR = Color.WHITE; + private static final int INCOGNITO_BACKGROUND_COLOR = Color.GRAY; @Mock BottomControlsCoordinator.BottomControlsVisibilityController mVisibilityController; @Mock TabGroupUiMediator.ResetHandler mResetHandler; @@ -188,7 +191,9 @@ mLayoutStateProviderSupplier, mIncognitoStateProvider, mDialogControllerSupplier, - mOmniboxFocusStateSupplier); + mOmniboxFocusStateSupplier, + PRIMARY_BACKGROUND_COLOR, + INCOGNITO_BACKGROUND_COLOR); if (currentTab == null) { verifyNeverReset(); @@ -1022,6 +1027,22 @@ mIncognitoStateObserverArgumentCaptor.getValue().onIncognitoStateChanged(true); assertThat(mModel.get(TabGroupUiProperties.IS_INCOGNITO), equalTo(true)); + assertThat( + mModel.get(TabGroupUiProperties.BACKGROUND_COLOR), + equalTo(INCOGNITO_BACKGROUND_COLOR)); + mVisibilityControllerInOrder + .verify(mVisibilityController) + .setBottomControlsColor(INCOGNITO_BACKGROUND_COLOR); + + mIncognitoStateObserverArgumentCaptor.getValue().onIncognitoStateChanged(false); + + assertThat(mModel.get(TabGroupUiProperties.IS_INCOGNITO), equalTo(false)); + assertThat( + mModel.get(TabGroupUiProperties.BACKGROUND_COLOR), + equalTo(PRIMARY_BACKGROUND_COLOR)); + mVisibilityControllerInOrder + .verify(mVisibilityController) + .setBottomControlsColor(PRIMARY_BACKGROUND_COLOR); } @Test
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index b3bd8a9..544e8ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -809,6 +809,7 @@ mContentContainer, mStartSurfaceSupplier, mTabSwitcherSupplier, + getTabModelSelectorSupplier(), getBrowserControlsManager(), getTabContentManagerSupplier(), mRootUiCoordinator::getTopUiThemeColorProvider, @@ -843,6 +844,7 @@ mContentContainer, mStartSurfaceSupplier, mTabSwitcherSupplier, + getTabModelSelectorSupplier(), getBrowserControlsManager(), getTabContentManagerSupplier(), mRootUiCoordinator::getTopUiThemeColorProvider, @@ -1782,8 +1784,7 @@ } } - // TODO(b/332766879): Call maybeShowTabSwitcher() here to handle data sharing intent on - // new Chrome instances. + maybeShowTabSwitcher(intent); } finally { TraceEvent.end("ChromeTabbedActivity.initializeState"); } @@ -4017,7 +4018,8 @@ boolean shouldShowTabSwitcher = IntentUtils.safeGetBooleanExtra( intent, DataSharingNotificationManager.DATA_SHARING_EXTRA, false) - && IntentHandler.wasIntentSenderChrome(intent); + && IntentHandler.wasIntentSenderChrome(intent) + && !mTabModelSelector.isIncognitoSelected(); if (shouldShowTabSwitcher) { // TODO(haileywang): Close the tab grid dialog when showing tab switcher from this path. TabModelUtils.runOnTabStateInitialized(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillIbanEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillIbanEditor.java new file mode 100644 index 0000000..e6e393f --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillIbanEditor.java
@@ -0,0 +1,105 @@ +// Copyright 2024 The Chromium Authors +// 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.autofill.settings; + +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; + +import androidx.annotation.NonNull; + +import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillEditorBase; +import org.chromium.chrome.browser.autofill.PersonalDataManager; +import org.chromium.chrome.browser.autofill.PersonalDataManager.Iban; +import org.chromium.chrome.browser.autofill.PersonalDataManagerFactory; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.settings.ProfileDependentSetting; +import org.chromium.ui.modaldialog.DialogDismissalCause; +import org.chromium.ui.modaldialog.ModalDialogManager; + +/** The base class for adding, editing, and deleting an IBAN. */ +public abstract class AutofillIbanEditor extends AutofillEditorBase + implements ProfileDependentSetting { + private Profile mProfile; + private Supplier<ModalDialogManager> mModalDialogManagerSupplier; + protected Iban mIban; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = super.onCreateView(inflater, container, savedInstanceState); + + // Do not use autofill for the fields. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + getActivity() + .getWindow() + .getDecorView() + .setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); + } + + PersonalDataManager personalDataManager = + PersonalDataManagerFactory.getForProfile(getProfile()); + mIban = personalDataManager.getIban(mGUID); + return v; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.delete_menu_id) { + showDeletePaymentMethodConfirmationDialog(); + return true; + } + // TODO(b/332954304): Add help button to IBAN editor. + return super.onOptionsItemSelected(item); + } + + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {} + + @Override + public void setProfile(Profile profile) { + mProfile = profile; + } + + /** Return the {@link Profile} associated with the IBAN being edited. */ + public Profile getProfile() { + return mProfile; + } + + /** + * Sets Supplier for {@link ModalDialogManager} used to display {@link + * AutofillDeletePaymentMethodConfirmationDialog}. + */ + public void setModalDialogManagerSupplier( + @NonNull Supplier<ModalDialogManager> modalDialogManagerSupplier) { + mModalDialogManagerSupplier = modalDialogManagerSupplier; + } + + private void showDeletePaymentMethodConfirmationDialog() { + assert mModalDialogManagerSupplier != null; + + ModalDialogManager modalDialogManager = mModalDialogManagerSupplier.get(); + assert modalDialogManager != null; + + AutofillDeletePaymentMethodConfirmationDialog dialog = + new AutofillDeletePaymentMethodConfirmationDialog( + modalDialogManager, + getContext(), + dismissalCause -> { + if (dismissalCause == DialogDismissalCause.POSITIVE_BUTTON_CLICKED) { + deleteEntry(); + getActivity().finish(); + } + }, + /* titleResId= */ R.string.autofill_iban_delete_confirmation_title); + dialog.show(); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java index 190d259..af57253 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditor.java
@@ -9,7 +9,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; @@ -23,41 +22,31 @@ import org.chromium.base.Callback; import org.chromium.build.annotations.UsedByReflection; import org.chromium.chrome.R; -import org.chromium.chrome.browser.autofill.AutofillEditorBase; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.Iban; import org.chromium.chrome.browser.autofill.PersonalDataManagerFactory; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.settings.ProfileDependentSetting; import org.chromium.components.autofill.IbanRecordType; /** * This class creates a view for adding and editing a local IBAN. A local IBAN gets saved to the * user's device only. */ -public class AutofillLocalIbanEditor extends AutofillEditorBase implements ProfileDependentSetting { +public class AutofillLocalIbanEditor extends AutofillIbanEditor { private static Callback<Fragment> sObserverForTest; - protected Iban mIban; protected Button mDoneButton; protected EditText mNickname; protected TextInputLayout mNicknameLabel; protected EditText mValue; - private Profile mProfile; - @UsedByReflection("AutofillPaymentMethodsFragment.java") public AutofillLocalIbanEditor() {} @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // TODO(b/309163678): Disable autofill for the fields. View v = super.onCreateView(inflater, container, savedInstanceState); - PersonalDataManager personalDataManager = - PersonalDataManagerFactory.getForProfile(mProfile); - mIban = personalDataManager.getIban(mGUID); mDoneButton = (Button) v.findViewById(R.id.button_primary); mNickname = (EditText) v.findViewById(R.id.iban_nickname_edit); mNicknameLabel = (TextInputLayout) v.findViewById(R.id.iban_nickname_label); @@ -85,11 +74,6 @@ } @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - // TODO(b/309163678): Update this once the AutofillIbanEditor class is added. - } - - @Override public void afterTextChanged(Editable s) { updateSaveButtonEnabled(); } @@ -109,7 +93,7 @@ : IbanRecordType.LOCAL_IBAN, /* value= */ mValue.getText().toString()); PersonalDataManager personalDataManager = - PersonalDataManagerFactory.getForProfile(mProfile); + PersonalDataManagerFactory.getForProfile(getProfile()); String guid = personalDataManager.addOrUpdateLocalIban(iban); // Return true if the GUID is non-empty (successful operation), and false if the GUID is // empty (unsuccessful). @@ -118,7 +102,9 @@ @Override protected void deleteEntry() { - // TODO(b/309163615): User can delete existing IBANs from settings page. + if (mGUID != null) { + PersonalDataManagerFactory.getForProfile(getProfile()).deleteIban(mGUID); + } } @Override @@ -149,12 +135,7 @@ private void updateSaveButtonEnabled() { // Enable save button if IBAN value is valid. mDoneButton.setEnabled( - PersonalDataManagerFactory.getForProfile(mProfile) + PersonalDataManagerFactory.getForProfile(getProfile()) .isValidIban(mValue.getText().toString())); } - - @Override - public void setProfile(Profile profile) { - mProfile = profile; - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java index b4e41936..aac98ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -700,4 +700,12 @@ public boolean isRunningAnimations() { return false; } + + /** + * Called when the desktop windowing mode changes. + * + * @param isInDesktopWindow Whether the app is in a desktop window. {@code true} if the app + * entered desktop windowing mode, {@code false} if the app exited desktop windowing mode. + */ + public void onDesktopWindowingModeChanged(boolean isInDesktopWindow) {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java index 5034f09e..c778293b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -88,6 +88,7 @@ // Lazy Tab Switcher Init private final Supplier<StartSurface> mStartSurfaceSupplier; private final Supplier<TabSwitcher> mTabSwitcherSupplier; + private final Supplier<TabModelSelector> mTabModelSelectorSupplier; private final ScrimCoordinator mScrimCoordinator; private final Callable<ViewGroup> mCreateTabSwitcherOrStartSurfaceCallable; @@ -110,6 +111,7 @@ * StartSurfaceHomeLayout if it has value. * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher. Used * to create TabSwitcherLayout if it has value. + * @param tabModelSelectorSupplier Supplier for an interface to talk to the Tab Model Selector. * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top * controls. * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance. @@ -125,6 +127,7 @@ ViewGroup contentContainer, Supplier<StartSurface> startSurfaceSupplier, Supplier<TabSwitcher> tabSwitcherSupplier, + Supplier<TabModelSelector> tabModelSelectorSupplier, BrowserControlsStateProvider browserControlsStateProvider, ObservableSupplier<TabContentManager> tabContentManagerSupplier, Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, @@ -141,6 +144,7 @@ mStartSurfaceSupplier = startSurfaceSupplier; mTabSwitcherSupplier = tabSwitcherSupplier; + mTabModelSelectorSupplier = tabModelSelectorSupplier; mScrimCoordinator = scrimCoordinator; mCreateTabSwitcherOrStartSurfaceCallable = delayedTabSwitcherOrStartSurfaceCallable; mHubLayoutDependencyHolder = hubLayoutDependencyHolder; @@ -262,7 +266,8 @@ /* updateHost= */ this, renderHost, /* layoutStateProvider= */ this, - hubLayoutDependencyHolder); + hubLayoutDependencyHolder, + mTabModelSelectorSupplier); if (mTabContentManagerSupplier.hasValue()) { mHubLayout.setTabContentManager(mTabContentManagerSupplier.get()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java index 26c6507..3f4ae33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -44,6 +44,7 @@ * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher when * Start surface refactor is enabled. Used to create overviewLayout if it has value, * otherwise will use the accessibility overview layout. + * @param tabModelSelectorSupplier Supplier for an interface to talk to the Tab Model Selector. * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top * controls. * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance. @@ -57,6 +58,7 @@ ViewGroup contentContainer, Supplier<StartSurface> startSurfaceSupplier, Supplier<TabSwitcher> tabSwitcherSupplier, + Supplier<TabModelSelector> tabModelSelectorSupplier, BrowserControlsStateProvider browserControlsStateProvider, ObservableSupplier<TabContentManager> tabContentManagerSupplier, Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, @@ -67,6 +69,7 @@ contentContainer, startSurfaceSupplier, tabSwitcherSupplier, + tabModelSelectorSupplier, browserControlsStateProvider, tabContentManagerSupplier, topUiThemeColorProvider,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java index a012b5c..17fd0d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager.TabModelStartupInfo; import org.chromium.chrome.browser.device.DeviceClassManager; +import org.chromium.chrome.browser.hub.HubLayout; import org.chromium.chrome.browser.hub.HubLayoutDependencyHolder; import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -70,6 +71,7 @@ * Start surface refactor is disabled. * @param tabSwitcherSupplier Supplier for an interface to talk to the Grid Tab Switcher when * Start surface refactor is enabled. + * @param tabModelSelectorSupplier Supplier for an interface to talk to the Tab Model Selector. * @param browserControlsStateProvider The {@link BrowserControlsStateProvider} for top * controls. * @param tabContentManagerSupplier Supplier of the {@link TabContentManager} instance. @@ -96,6 +98,7 @@ ViewGroup contentContainer, Supplier<StartSurface> startSurfaceSupplier, Supplier<TabSwitcher> tabSwitcherSupplier, + Supplier<TabModelSelector> tabModelSelectorSupplier, BrowserControlsStateProvider browserControlsStateProvider, ObservableSupplier<TabContentManager> tabContentManagerSupplier, Supplier<TopUiThemeColorProvider> topUiThemeColorProvider, @@ -117,6 +120,7 @@ contentContainer, startSurfaceSupplier, tabSwitcherSupplier, + tabModelSelectorSupplier, browserControlsStateProvider, tabContentManagerSupplier, topUiThemeColorProvider,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 05ef800..d7bea33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -3172,7 +3172,8 @@ return tab == mStripTabsVisuallyOrdered[mStripTabsVisuallyOrdered.length - 1]; } - private void updateTabAttachState( + @VisibleForTesting + void updateTabAttachState( StripLayoutTab tab, boolean attached, ArrayList<Animator> animationList) { float startValue = attached ? FOLIO_DETACHED_BOTTOM_MARGIN_DP : FOLIO_ATTACHED_BOTTOM_MARGIN_DP; @@ -3374,7 +3375,12 @@ // 5. Reattach the folio container to the toolbar. if (mInteractingTab != null) { mInteractingTab.setIsReordering(false); - updateTabAttachState(mInteractingTab, true, animationList); + + // Skip reattachment for tab drop to avoid exposing bottom indicator underneath the tab + // container. + if (!mReorderingForTabDrop || !mInteractingTab.getFolioAttached()) { + updateTabAttachState(mInteractingTab, true, animationList); + } } // 6. Reset the tab drop state. Must occur after the rest of the state is reset, since some @@ -3591,8 +3597,6 @@ .start(); } - // TODO(crbug.com/332780745): Remove tab container detachment for tab drop in Tab Group - // Indicators. private void setBackgroundTabContainerVisible(StripLayoutTab tab, boolean visible) { if (mReorderingForTabDrop || tab != mInteractingTab) { float opacity = visible ? TAB_OPACITY_VISIBLE_BACKGROUND : TAB_OPACITY_HIDDEN;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java index d5afed88f..f86fa9d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java
@@ -8,7 +8,8 @@ import android.text.TextUtils; import android.webkit.URLUtil; -import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.base.CommandLine; +import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; import org.chromium.ui.base.DeviceFormFactor; @@ -56,10 +57,9 @@ * @see DeviceFormFactor#isNonMultiDisplayContextOnTablet(Context). */ public static boolean usePopupContextMenuForContext(Context context) { - if (context == null) return false; + if (context == null || !CommandLine.isInitialized()) return false; - return ChromeFeatureList.isEnabled( - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES) - || DeviceFormFactor.isNonMultiDisplayContextOnTablet(context); + return DeviceFormFactor.isNonMultiDisplayContextOnTablet(context) + || CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java index 0c460c2..f05198f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -1442,9 +1442,7 @@ } if (mBlockingStatus3pcd != CookieBlocking3pcdStatus.NOT_IN3PCD) { if (!mCookieControlsVisible || !mThirdPartyCookiesBlocked) return; - mPageInfoIPHController.showCookieControlsReminderIPH( - COOKIE_CONTROLS_ICON_DISPLAY_TIMEOUT, - R.string.cookie_controls_reminder_iph_message); + // TODO(b/332761678): Add reminder IPH here. } else if (mShouldHighlightCookieControlsIcon) { mPageInfoIPHController.showCookieControlsIPH( COOKIE_CONTROLS_ICON_DISPLAY_TIMEOUT, R.string.cookie_controls_iph_message);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java index f2e48a48d7..920a570 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.dependency_injection; import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.APP_CONTEXT; -import static org.chromium.chrome.browser.dependency_injection.ChromeCommonQualifiers.LAST_USED_REGULAR_PROFILE; import android.content.Context; @@ -24,8 +23,6 @@ import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor; import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager; import org.chromium.chrome.browser.webapps.WebappRegistry; @@ -41,12 +38,6 @@ } @Provides - @Named(LAST_USED_REGULAR_PROFILE) - public Profile provideLastUsedRegularProfile() { - return ProfileManager.getLastUsedRegularProfile(); - } - - @Provides public SharedPreferencesManager providesChromeSharedPreferences() { return ChromeSharedPreferences.getInstance(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeCommonQualifiers.java b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeCommonQualifiers.java index 4a2605e3..3d71964 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeCommonQualifiers.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeCommonQualifiers.java
@@ -9,8 +9,6 @@ * when it is ambiguous. */ public interface ChromeCommonQualifiers { - String LAST_USED_REGULAR_PROFILE = "LAST_USED_REGULAR_PROFILE"; - String ACTIVITY_CONTEXT = "ACTIVITY_CONTEXT"; String APP_CONTEXT = "APP_CONTEXT";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java index 1878b66..44c5da9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java
@@ -10,6 +10,7 @@ import android.app.Activity; import android.view.View; +import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -507,6 +508,13 @@ } @Override + public void notifyBackgroundColor(@ColorInt int color) { + for (BrowserControlsStateProvider.Observer obs : mControlsObservers) { + obs.onBottomControlsBackgroundColorChanged(color); + } + } + + @Override public void addObserver(BrowserControlsStateProvider.Observer obs) { mControlsObservers.addObserver(obs); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java index 86205a8..c12add9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayout.java
@@ -17,6 +17,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.widget.FrameLayout; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; @@ -29,6 +30,7 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.base.supplier.Supplier; import org.chromium.base.supplier.SyncOneshotSupplierImpl; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; @@ -50,6 +52,7 @@ import org.chromium.chrome.browser.tab.TabLoadIfNeededCaller; import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab_ui.TabContentManager; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.ui.base.DeviceFormFactor; @@ -103,13 +106,15 @@ * @param layoutStateProvider The {@link LayoutStateProvider} for the {@link LayoutManager}. * @param dependencyHolder The {@link HubLayoutDependencyHolder} that holds dependencies for * HubLayout. + * @param tabModelSelectorSupplier Supplier for an interface to talk to the Tab Model Selector. */ public HubLayout( @NonNull Context context, @NonNull LayoutUpdateHost updateHost, @NonNull LayoutRenderHost renderHost, @NonNull LayoutStateProvider layoutStateProvider, - @NonNull HubLayoutDependencyHolder dependencyHolder) { + @NonNull HubLayoutDependencyHolder dependencyHolder, + Supplier<TabModelSelector> tabModelSelectorSupplier) { super(context, updateHost, renderHost); mPreviousLayoutTypeSupplier.set(layoutStateProvider.getActiveLayoutType()); @@ -129,6 +134,24 @@ mPaneManager.getFocusedPaneSupplier().addObserver(mOnPaneFocused); mScrimController = dependencyHolder.getScrimController(); mOnToolbarAlphaChange = dependencyHolder.getOnToolbarAlphaChange(); + mTabModelSelector = tabModelSelectorSupplier.get(); + } + + @Override + public void onDesktopWindowingModeChanged(boolean isInDesktopWindow) { + super.onDesktopWindowingModeChanged(isInDesktopWindow); + // If desktop windowing mode changes while the HubLayout is active, adjust the container + // view's y-offset. This update will be posted because it has been observed that an + // immediate update causes unexpected visual positioning in this scenario, potentially + // because the top margin for the view is also updated at nearly the same time, but the root + // cause is unknown. + // TODO (crbug/335651375): Investigate and remove the use of a PostTask for this update. + // TODO (crbug/334156232): Also update container height. + if (isActive()) { + PostTask.postTask( + TaskTraits.UI_DEFAULT, + () -> mHubController.getContainerView().setY(getContainerYOffset())); + } } /** Returns the current {@link HubLayoutAnimationType}. */ @@ -594,7 +617,7 @@ if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(getContext())) { return TranslateHubLayoutAnimationFactory.createTranslateUpAnimatorProvider( - containerView, mScrimController, TRANSLATE_DURATION_MS); + containerView, mScrimController, TRANSLATE_DURATION_MS, getContainerYOffset()); } else if (mPreviousLayoutTypeSupplier.get() == LayoutType.START_SURFACE || pane == null) { return FadeHubLayoutAnimationFactory.createFadeInAnimatorProvider( containerView, FADE_DURATION_MS, mOnToolbarAlphaChange); @@ -609,7 +632,7 @@ if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(getContext())) { return TranslateHubLayoutAnimationFactory.createTranslateDownAnimatorProvider( - containerView, mScrimController, TRANSLATE_DURATION_MS); + containerView, mScrimController, TRANSLATE_DURATION_MS, getContainerYOffset()); } else if (nextLayoutType == LayoutType.START_SURFACE || pane == null) { return FadeHubLayoutAnimationFactory.createFadeOutAnimatorProvider( containerView, FADE_DURATION_MS, mOnToolbarAlphaChange); @@ -711,4 +734,17 @@ private int getIdForTab(@Nullable Tab tab) { return tab == null ? Tab.INVALID_TAB_ID : tab.getId(); } + + /** + * @return The y-offset for the container view that may be impacted by the status indicator and + * app header heights. + */ + private float getContainerYOffset() { + var params = (FrameLayout.LayoutParams) mHubController.getContainerView().getLayoutParams(); + return params.topMargin; + } + + public HubController getHubControllerForTesting() { + return mHubController; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java index 3d1e327f..7eef1a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/HubLayoutUnitTest.java
@@ -39,6 +39,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.FrameLayout.LayoutParams; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.filters.SmallTest; @@ -58,6 +59,7 @@ import org.chromium.base.Callback; import org.chromium.base.supplier.LazyOneshotSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.base.supplier.Supplier; import org.chromium.base.supplier.SyncOneshotSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; @@ -142,6 +144,7 @@ private HubContainerView mHubContainerView; private SyncOneshotSupplierImpl<HubLayoutAnimator> mHubLayoutAnimatorSupplier; + private Supplier<TabModelSelector> mTabModelSelectorSupplier; private ObservableSupplierImpl<Pane> mPaneSupplier = new ObservableSupplierImpl<>(); @Before @@ -260,6 +263,8 @@ mFrameLayout = new FrameLayout(mActivity); mHubContainerView = new HubContainerView(mActivity); View hubLayout = LayoutInflater.from(activity).inflate(R.layout.hub_layout, null); + mHubContainerView.setLayoutParams( + new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mHubContainerView.addView(hubLayout); mActivity.setContentView(mFrameLayout); @@ -275,6 +280,7 @@ new HubLayoutDependencyHolder( hubManagerSupplier, rootViewSupplier, mScrimController, mOnAlphaChange); + mTabModelSelectorSupplier = () -> mTabModelSelector; mHubLayout = spy( new HubLayout( @@ -282,7 +288,8 @@ mUpdateHost, mRenderHost, mLayoutStateProvider, - dependencyHolder)); + dependencyHolder, + mTabModelSelectorSupplier)); mHubLayout.setTabModelSelector(mTabModelSelector); mHubLayout.setTabContentManager(mTabContentManager); mHubLayout.onFinishNativeInitialization();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java index 7435e131..de1ba8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentlyClosedBridge.java
@@ -88,7 +88,7 @@ // Ensure that the color is set before merging the tabs into a group on restore, to indicate // that this is not going to be a new group creation. - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { groupFilter.setTabGroupColor(rootId, color); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java index bd303bb..71351451 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
@@ -106,7 +106,7 @@ public GURL getCurrentGurl() { if (GURL.isEmptyOrInvalid(mGurl)) { assert LibraryLoader.getInstance().isInitialized(); - mGurl = new GURL(SearchActivityPreferencesManager.getCurrent().searchEngineUrl); + mGurl = SearchActivityPreferencesManager.getCurrent().searchEngineUrl; } return mGurl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java index 44fb39ab..e219cfd8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.autofill.options.AutofillOptionsCoordinator; import org.chromium.chrome.browser.autofill.options.AutofillOptionsFragment; import org.chromium.chrome.browser.autofill.settings.AutofillCreditCardEditor; +import org.chromium.chrome.browser.autofill.settings.AutofillIbanEditor; import org.chromium.chrome.browser.back_press.BackPressHelper; import org.chromium.chrome.browser.back_press.SecondaryActivityBackPressUma.SecondaryActivity; import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragmentBasic; @@ -643,6 +644,10 @@ ipProtectionSettingsFragment.setCustomTabIntentHelper( LaunchIntentDispatcher::createCustomTabActivityIntent); } + if (fragment instanceof AutofillIbanEditor) { + ((AutofillIbanEditor) fragment) + .setModalDialogManagerSupplier(getModalDialogManagerSupplier()); + } } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java index ffd0a70..60cfde91 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java
@@ -81,7 +81,7 @@ String title = TabGroupTitleUtils.getTabGroupTitle(rootId); // Give a tab group the first color in the color list as a placeholder. @TabGroupColorId int color = TabGroupColorId.GREY; - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { color = TabGroupColorUtils.getOrCreateTabGroupColor(rootId, mTabGroupModelFilter); } List<Tab> groupTabs = new ArrayList<Tab>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java new file mode 100644 index 0000000..f0cea61 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserver.java
@@ -0,0 +1,131 @@ +// Copyright 2024 The Chromium Authors +// 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.tabbed_mode; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + +import org.chromium.base.ObserverList; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; + +/** + * An observer class that listens for changes in UI components that are attached to the bottom of + * the screen, bordering the OS navigation bar. This class then aggregates that information and + * notifies its own observers of properties of the UI currently bordering ("attached to") the + * navigation bar. + */ +public class BottomAttachedUiObserver implements BrowserControlsStateProvider.Observer { + /** + * An observer to be notified of changes to what kind of UI is currently bordering the bottom of + * the screen. + */ + public interface Observer { + void onBottomAttachedColorChanged(@Nullable @ColorInt Integer color); + } + + private final ObserverList<Observer> mObservers; + private @Nullable @ColorInt Integer mBottomAttachedColor; + + private final BrowserControlsStateProvider mBrowserControlsStateProvider; + private int mBottomControlsHeight; + private @Nullable @ColorInt Integer mBottomControlsColor; + private boolean mBottomControlsAreVisible; + + /** + * Build the observer that listens to changes in the UI bordering the bottom. + * + * @param browserControlsStateProvider Supplies a {@link BrowserControlsStateProvider} for the + * browser controls. + */ + public BottomAttachedUiObserver(BrowserControlsStateProvider browserControlsStateProvider) { + mObservers = new ObserverList<>(); + + mBrowserControlsStateProvider = browserControlsStateProvider; + mBrowserControlsStateProvider.addObserver(this); + } + + /** + * @param observer The observer to add. + */ + public void addObserver(Observer observer) { + mObservers.addObserver(observer); + } + + /** + * @param observer The observer to remove. + */ + public void removeObserver(Observer observer) { + mObservers.removeObserver(observer); + } + + public void destroy() { + if (mBrowserControlsStateProvider != null) { + mBrowserControlsStateProvider.removeObserver(this); + } + } + + private void updateBottomAttachedColor() { + @Nullable + @ColorInt + Integer bottomAttachedColor = calculateBottomAttachedColor(); + if (mBottomAttachedColor == null && bottomAttachedColor == null) { + return; + } + if (mBottomAttachedColor != null && mBottomAttachedColor.equals(bottomAttachedColor)) { + return; + } + mBottomAttachedColor = bottomAttachedColor; + for (Observer observer : mObservers) { + observer.onBottomAttachedColorChanged(mBottomAttachedColor); + } + } + + private @Nullable @ColorInt Integer calculateBottomAttachedColor() { + if (mBottomControlsAreVisible) { + return mBottomControlsColor; + } + return null; + } + + // Browser Controls (Tab group UI, Read Aloud) + + @Override + public void onControlsOffsetChanged( + int topOffset, + int topControlsMinHeightOffset, + int bottomOffset, + int bottomControlsMinHeightOffset, + boolean needsAnimate) { + updateBrowserControlsVisibility( + // MiniPlayerMediator#shrinkBottomControls() sets the height to 1 and minHeight to 0 + // when hiding, instead of setting the height to 0. + // TODO(b/320750931): Clean up once the MiniPlayerMediator has been improved. + mBottomControlsHeight > 1 && bottomOffset < mBottomControlsHeight); + } + + @Override + public void onBottomControlsHeightChanged( + int bottomControlsHeight, int bottomControlsMinHeight) { + mBottomControlsHeight = bottomControlsHeight; + // MiniPlayerMediator#shrinkBottomControls() sets the height to 1 and minHeight to 0 when + // hiding, instead of setting the height to 0. + // TODO(b/320750931): Clean up once the MiniPlayerMediator has been improved. + updateBrowserControlsVisibility(bottomControlsHeight > 1); + } + + @Override + public void onBottomControlsBackgroundColorChanged(@ColorInt int color) { + mBottomControlsColor = color; + updateBottomAttachedColor(); + } + + private void updateBrowserControlsVisibility(boolean bottomControlsAreVisible) { + if (bottomControlsAreVisible == mBottomControlsAreVisible) { + return; + } + mBottomControlsAreVisible = bottomControlsAreVisible; + updateBottomAttachedColor(); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorController.java index 2c8acb70..2d3bd74 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorController.java
@@ -21,6 +21,7 @@ import org.chromium.base.MathUtils; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.chrome.R; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.fullscreen.FullscreenOptions; @@ -42,7 +43,7 @@ /** Controls the bottom system navigation bar color for the provided {@link Window}. */ @RequiresApi(Build.VERSION_CODES.O_MR1) -class TabbedNavigationBarColorController { +class TabbedNavigationBarColorController implements BottomAttachedUiObserver.Observer { private static final String TAG = "NavBarColorCntrller"; private final Window mWindow; private final ViewGroup mRootView; @@ -68,9 +69,11 @@ private final Callback<EdgeToEdgeController> mEdgeToEdgeRegisterChangeObserverCallback; private EdgeToEdgeController mEdgeToEdgeController; @Nullable private ChangeObserver mEdgeToEdgeChangeObserver; + private final BottomAttachedUiObserver mBottomAttachedUiObserver; private @Nullable Tab mActiveTab; private TabObserver mTabObserver; + @Nullable private @ColorInt Integer mBottomAttachedUiColor; /** * Creates a new {@link TabbedNavigationBarColorController} instance. @@ -91,7 +94,8 @@ TabModelSelector tabModelSelector, ObservableSupplier<LayoutManager> layoutManagerSupplier, FullscreenManager fullscreenManager, - ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier) { + ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier, + BrowserControlsStateProvider browserControlsStateProvider) { assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1; mWindow = window; @@ -102,6 +106,9 @@ mLightNavigationBar = mContext.getResources().getBoolean(R.bool.window_light_navigation_bar); + mBottomAttachedUiObserver = new BottomAttachedUiObserver(browserControlsStateProvider); + mBottomAttachedUiObserver.addObserver(this); + mTabModelSelector = tabModelSelector; mTabModelSelectorObserver = new TabModelSelectorObserver() { @@ -179,11 +186,21 @@ mEdgeToEdgeChangeObserver = null; } mEdgeToEdgeControllerSupplier.removeObserver(mEdgeToEdgeRegisterChangeObserverCallback); + if (mBottomAttachedUiObserver != null) { + mBottomAttachedUiObserver.removeObserver(this); + mBottomAttachedUiObserver.destroy(); + } + } + + @Override + public void onBottomAttachedColorChanged(@Nullable @ColorInt Integer color) { + mBottomAttachedUiColor = color; + updateNavigationBarColor(); } /** - * @param layoutManager The {@link LayoutStateProvider} used to determine whether - * overview mode is showing. + * @param layoutManager The {@link LayoutStateProvider} used to determine whether overview mode + * is showing. */ private void setLayoutManager(LayoutManager layoutManager) { if (mLayoutManager != null) { @@ -301,6 +318,9 @@ @ColorInt private int getNavigationBarColor(boolean forceDarkNavigationBar) { + if (useBottomAttachedUiColor()) { + return mBottomAttachedUiColor; + } if (useActiveTabColor()) { return mActiveTab.getBackgroundColor(); } @@ -313,6 +333,9 @@ @VisibleForTesting @ColorInt int getNavigationBarDividerColor(boolean forceDarkNavigationBar) { + if (useBottomAttachedUiColor()) { + return mBottomAttachedUiColor; + } if (useActiveTabColor()) { return mActiveTab.getBackgroundColor(); } @@ -325,6 +348,12 @@ return ColorUtils.overlayColor(color, mDefaultScrimColor, mNavigationBarScrimFraction); } + private boolean useBottomAttachedUiColor() { + return ChromeFeatureList.sNavBarColorMatchesTabBackground.isEnabled() + && mBottomAttachedUiColor != null + && getBottomInset() == 0; + } + private boolean useActiveTabColor() { return ChromeFeatureList.sNavBarColorMatchesTabBackground.isEnabled() && mLayoutManager != null @@ -351,6 +380,10 @@ return useActiveTabColor(); } + boolean getUseBottomAttachedUiColorForTesting() { + return useBottomAttachedUiColor(); + } + int getNavigationBarColorForTesting() { return mNavigationBarColor; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index 9df7bb3..0384421 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -431,11 +431,26 @@ @Override public void onDesktopWindowingModeChanged(boolean isInDesktopWindow) { desktopWindowModeSupplier.set(isInDesktopWindow); + if (hubManagerSupplier.hasValue()) { + hubManagerSupplier.get().setAppHeaderHeight(getAppHeaderHeight()); + } + if (layoutManagerSupplier.get() != null) { + var layout = layoutManagerSupplier.get().getActiveLayout(); + layout.onDesktopWindowingModeChanged(isInDesktopWindow); + } } }; initAppHeaderCoordinator(); } + private int getAppHeaderHeight() { + if (VERSION.SDK_INT < VERSION_CODES.R || mAppHeaderCoordinator == null) return 0; + return (mAppHeaderCoordinator.isInDesktopWindow() + && mAppHeaderCoordinator.getAppHeaderState() != null) + ? mAppHeaderCoordinator.getAppHeaderState().getAppHeaderHeight() + : 0; + } + @Override public void onDestroy() { if (mSystemUiCoordinator != null) mSystemUiCoordinator.destroy(); @@ -541,7 +556,8 @@ mTabModelSelectorSupplier.get(), mLayoutManagerSupplier, mFullscreenManager, - mEdgeToEdgeControllerSupplier); + mEdgeToEdgeControllerSupplier, + mBrowserControlsManager); } @Override @@ -671,7 +687,7 @@ .addTouchEventObserver(mDragDropTouchObserver); } - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { Runnable onDialogAcceptedRunnable = () -> { if (!mTabModelSelectorSupplier.get().isIncognitoSelected()) { @@ -1242,6 +1258,8 @@ mAppHeaderDelegateSupplier, mTabStripTransitionCoordinatorSupplier); mAppHeaderCoordinator.addObserver(mAppHeaderObserver); + mHubManagerSupplier.onAvailable( + hubManager -> hubManager.setAppHeaderHeight(getAppHeaderHeight())); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedSystemUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedSystemUiCoordinator.java index 0dfa81db..51640f98 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedSystemUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedSystemUiCoordinator.java
@@ -10,6 +10,7 @@ import androidx.annotation.Nullable; import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.layouts.LayoutManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -34,13 +35,16 @@ * @param fullscreenManager The {@link FullscreenManager} used for containing activity * @param edgeToEdgeControllerSupplier Supplies an {@link EdgeToEdgeController} to detect when * the UI is being drawn edge to edge. + * @param browserControlsStateProvider Supplies a {@link BrowserControlsStateProvider} for the + * browser controls. */ public TabbedSystemUiCoordinator( Window window, TabModelSelector tabModelSelector, @Nullable ObservableSupplier<LayoutManager> layoutManagerSupplier, FullscreenManager fullscreenManager, - ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier) { + ObservableSupplier<EdgeToEdgeController> edgeToEdgeControllerSupplier, + BrowserControlsStateProvider browserControlsStateProvider) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { assert layoutManagerSupplier != null; mNavigationBarColorController = @@ -49,7 +53,8 @@ tabModelSelector, layoutManagerSupplier, fullscreenManager, - edgeToEdgeControllerSupplier); + edgeToEdgeControllerSupplier, + browserControlsStateProvider); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java index 21dfd3d9..5a9068a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java
@@ -32,7 +32,6 @@ import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator; import org.chromium.chrome.browser.firstrun.FirstRunStatus; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -52,11 +51,11 @@ /** Integration tests for drag interactions with context menu. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) -@EnableFeatures({ - ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES +@CommandLineFlags.Add({ + ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeSwitches.FORCE_CONTEXT_MENU_POPUP }) +@EnableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU}) @Batch(Batch.PER_CLASS) public class ContextMenuDragTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditorTest.java index 6ce2d3c..dff048f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalIbanEditorTest.java
@@ -6,7 +6,14 @@ import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.os.Bundle; +import android.view.MenuItem; import androidx.test.filters.MediumTest; @@ -16,17 +23,26 @@ import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.util.Features; import org.chromium.chrome.browser.autofill.AutofillEditorBase; import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.Iban; +import org.chromium.chrome.browser.autofill.PersonalDataManagerFactory; import org.chromium.chrome.browser.settings.SettingsActivity; import org.chromium.chrome.browser.settings.SettingsActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.R; import org.chromium.components.autofill.IbanRecordType; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; +// TODO(b/309163597): Add Robolectric tests to test the local editor behavior. @RunWith(ChromeJUnit4ClassRunner.class) public class AutofillLocalIbanEditorTest { @Rule public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); @@ -36,6 +52,8 @@ public final SettingsActivityTestRule<AutofillLocalIbanEditor> mSettingsActivityTestRule = new SettingsActivityTestRule<>(AutofillLocalIbanEditor.class); + @Mock private ObservableSupplierImpl<ModalDialogManager> mModalDialogManagerSupplierMock; + @Mock private PersonalDataManager mPersonalDataManagerMock; private AutofillTestHelper mAutofillTestHelper; private Bundle fragmentArgs(String guid) { @@ -54,6 +72,7 @@ @Before public void setUp() { + MockitoAnnotations.initMocks(this); mAutofillTestHelper = new AutofillTestHelper(); } @@ -89,6 +108,21 @@ }); } + private void openDeletePaymentMethodConfirmationDialog( + AutofillLocalIbanEditor autofillLocalIbanEditorFragment, + ModalDialogManager modalDialogManager) { + when(mModalDialogManagerSupplierMock.get()).thenReturn(modalDialogManager); + autofillLocalIbanEditorFragment.setModalDialogManagerSupplier( + mModalDialogManagerSupplierMock); + + MenuItem deleteButton = mock(MenuItem.class); + when(deleteButton.getItemId()).thenReturn(R.id.delete_menu_id); + TestThreadUtils.runOnUiThreadBlocking( + () -> { + autofillLocalIbanEditorFragment.onOptionsItemSelected(deleteButton); + }); + } + @Test @MediumTest public void testValidIbanValueEnablesSaveButton() throws Exception { @@ -182,4 +216,56 @@ assertThat(autofillLocalIbanEditorFragment.mDoneButton.isEnabled()).isTrue(); } + + @Test + @MediumTest + public void deleteIbanConfirmationDialog_deleteEntryCanceled_dialogDismissed() + throws Exception { + String guid = mAutofillTestHelper.addOrUpdateLocalIban(VALID_BELGIUM_IBAN); + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalIbanEditor autofillLocalIbanEditorFragment = + (AutofillLocalIbanEditor) activity.getMainFragment(); + + PersonalDataManagerFactory.setInstanceForTesting(mPersonalDataManagerMock); + + FakeModalDialogManager fakeModalDialogManager = + new FakeModalDialogManager(ModalDialogManager.ModalDialogType.APP); + openDeletePaymentMethodConfirmationDialog( + autofillLocalIbanEditorFragment, fakeModalDialogManager); + + // Verify the dialog is open. + Assert.assertNotNull(fakeModalDialogManager.getShownDialogModel()); + TestThreadUtils.runOnUiThreadBlocking(() -> fakeModalDialogManager.clickNegativeButton()); + // Verify the dialog is closed. + Assert.assertNull(fakeModalDialogManager.getShownDialogModel()); + // Verify the IBAN entry is not deleted. + verify(mPersonalDataManagerMock, never()).deleteIban(guid); + } + + @Test + @MediumTest + public void deleteIbanConfirmationDialog_deleteEntryConfirmed_dialogDismissedAndEntryDeleted() + throws Exception { + String guid = mAutofillTestHelper.addOrUpdateLocalIban(VALID_BELGIUM_IBAN); + SettingsActivity activity = + mSettingsActivityTestRule.startSettingsActivity(fragmentArgs(guid)); + AutofillLocalIbanEditor autofillLocalIbanEditorFragment = + (AutofillLocalIbanEditor) activity.getMainFragment(); + + PersonalDataManagerFactory.setInstanceForTesting(mPersonalDataManagerMock); + + FakeModalDialogManager fakeModalDialogManager = + new FakeModalDialogManager(ModalDialogManager.ModalDialogType.APP); + openDeletePaymentMethodConfirmationDialog( + autofillLocalIbanEditorFragment, fakeModalDialogManager); + + // Verify the dialog is open. + Assert.assertNotNull(fakeModalDialogManager.getShownDialogModel()); + TestThreadUtils.runOnUiThreadBlocking(() -> fakeModalDialogManager.clickPositiveButton()); + // Verify the dialog is closed. + Assert.assertNull(fakeModalDialogManager.getShownDialogModel()); + // Verify the IBAN entry is deleted. + verify(mPersonalDataManagerMock, times(1)).deleteIban(guid); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java index d453397..9672fdc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
@@ -36,7 +36,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; @@ -251,7 +250,6 @@ */ @Test @MediumTest - @DisabledTest(message = "https://crbug.com/1112720") public void testToolbarVisibleCertificateError() throws ExecutionException, TimeoutException { final String pageWithoutCertError = mEmbeddedTestServerRule.getServer().getURL("/chrome/test/data/android/about.html");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java index 3f2abcd..5d7006d0e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -112,6 +112,7 @@ private TabModelSelector mTabModelSelector; private Supplier<StartSurface> mStartSurfaceSupplier; private OneshotSupplierImpl<TabSwitcher> mTabSwitcherSupplier; + private Supplier<TabModelSelector> mTabModelSelectorSupplier; private LayoutManagerChrome mManager; private LayoutManagerChromePhone mManagerPhone; @@ -233,6 +234,7 @@ container, mStartSurfaceSupplier, mTabSwitcherSupplier, + mTabModelSelectorSupplier, mBrowserControlsStateProvider, tabContentManagerSupplier, () -> mTopUiThemeColorProvider, @@ -673,6 +675,7 @@ }); mStartSurfaceSupplier = () -> mStartSurface; + mTabModelSelectorSupplier = () -> mTabModelSelector; } @After
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java index f79127f..b02bcafb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java
@@ -17,16 +17,16 @@ import org.junit.runner.RunWith; import org.chromium.base.FeatureList; -import org.chromium.base.FeatureList.TestValues; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType; -import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -62,8 +62,6 @@ private View mView; private View mFrame; - private FeatureList.TestValues mTestValues; - public ContextMenuRenderTest(boolean nightModeEnabled) { NightModeTestUtils.setUpNightModeForBlankUiTestActivity(nightModeEnabled); mRenderTestRule.setNightModeEnabled(nightModeEnabled); @@ -73,11 +71,6 @@ public void setUpTest() throws Exception { super.setUpTest(); - mTestValues = new TestValues(); - mTestValues.addFeatureFlagOverride( - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES, false); - FeatureList.setTestValues(mTestValues); - TestThreadUtils.runOnUiThreadBlocking( () -> { mListItems = new ModelList(); @@ -130,9 +123,8 @@ @Test @LargeTest @Feature({"RenderTest"}) + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void testContextMenuViewWithLink_Popup() throws IOException { - mTestValues.addFeatureFlagOverride( - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES, true); doTestContextMenuViewWithLink("context_menu_with_link_popup"); } @@ -146,9 +138,8 @@ @Test @LargeTest @Feature({"RenderTest"}) + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void testContextMenuViewWithImageLink_Popup() throws IOException { - mTestValues.addFeatureFlagOverride( - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES, true); doTestContextMenuViewWithImageLink("context_menu_with_image_link_popup"); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java index 81b2102..c4464b6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java
@@ -12,6 +12,7 @@ import android.graphics.Rect; import android.os.Build; +import android.widget.FrameLayout.LayoutParams; import android.widget.ImageButton; import androidx.annotation.RequiresApi; @@ -39,6 +40,7 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromeTablet; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.hub.HubLayout; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherLayout; import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; import org.chromium.chrome.browser.theme.ThemeUtils; @@ -140,6 +142,7 @@ .getTabSwitcherForTesting() .getController() .getTabSwitcherContainer(); + assertTrue( "Tab switcher container view y-offset should be non-zero.", tabSwitcherContainerView.getY() != 0); @@ -206,6 +209,98 @@ TabUiTestHelper.clickFirstCardFromTabSwitcher(activity); } + @Test + @MediumTest + @EnableFeatures(ChromeFeatureList.ANDROID_HUB) + public void testEnterTabSwitcherInDesktopWindow_HubLayout() { + ChromeTabbedActivity activity = mActivityTestRule.getActivity(); + + // Enter desktop windowing mode. + triggerDesktopWindowingModeChange(true); + // Enter the tab switcher. + TabUiTestHelper.enterTabSwitcher(activity); + + var layoutManager = (LayoutManagerChromeTablet) activity.getLayoutManager(); + var hubLayout = ((HubLayout) layoutManager.getTabSwitcherLayoutForTesting()); + var hubContainerView = hubLayout.getHubControllerForTesting().getContainerView(); + var params = (LayoutParams) hubContainerView.getLayoutParams(); + + CriteriaHelper.pollUiThread( + () -> { + Criteria.checkThat( + "Tab switcher container view y-offset should match the app header" + + " height.", + (int) hubContainerView.getY(), + Matchers.is(APP_HEADER_HEIGHT_PX)); + Criteria.checkThat( + "Tab switcher container view top margin should match the app header" + + " height.", + params.topMargin, + Matchers.is(APP_HEADER_HEIGHT_PX)); + }); + + // Exit desktop windowing mode. + triggerDesktopWindowingModeChange(false); + CriteriaHelper.pollUiThread( + () -> { + Criteria.checkThat( + "Tab switcher container view y-offset should be zero.", + hubContainerView.getY(), + Matchers.is(0f)); + }); + TabUiTestHelper.clickFirstCardFromTabSwitcher(activity); + } + + @Test + @MediumTest + @EnableFeatures(ChromeFeatureList.ANDROID_HUB) + public void testEnterDesktopWindowWithTabSwitcherActive_HubLayout() { + ChromeTabbedActivity activity = mActivityTestRule.getActivity(); + + // Enter the tab switcher. Desktop windowing mode is not active initially. + TabUiTestHelper.enterTabSwitcher(activity); + + var layoutManager = (LayoutManagerChromeTablet) activity.getLayoutManager(); + var hubLayout = ((HubLayout) layoutManager.getTabSwitcherLayoutForTesting()); + var hubContainerView = hubLayout.getHubControllerForTesting().getContainerView(); + var params = (LayoutParams) hubContainerView.getLayoutParams(); + + assertEquals( + "Tab switcher container view y-offset should be zero.", + 0, + hubContainerView.getY(), + 0.0); + assertEquals("Tab switcher container view top margin should be zero.", 0, params.topMargin); + + // Enter desktop windowing mode while the tab switcher is visible. + triggerDesktopWindowingModeChange(true); + + CriteriaHelper.pollUiThread( + () -> { + Criteria.checkThat( + "Tab switcher container view y-offset should match the app header" + + " height.", + (int) hubContainerView.getY(), + Matchers.is(APP_HEADER_HEIGHT_PX)); + Criteria.checkThat( + "Tab switcher container view top margin should match the app header" + + " height.", + params.topMargin, + Matchers.is(APP_HEADER_HEIGHT_PX)); + }); + + // Exit desktop windowing mode. + triggerDesktopWindowingModeChange(false); + CriteriaHelper.pollUiThread( + () -> { + Criteria.checkThat( + "Tab switcher container view y-offset should be zero.", + hubContainerView.getY(), + Matchers.is(0f)); + }); + TabUiTestHelper.clickFirstCardFromTabSwitcher(activity); + } + private void doTestOnTopResumedActivityChanged( boolean isInDesktopWindow, boolean isActivityFocused) { ToolbarFeatures.setIsTabStripLayoutOptimizationEnabledForTesting(true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java index 0b402b3..c92b8fbf 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillDeletePaymentMethodConfirmationDialogTest.java
@@ -90,7 +90,10 @@ public static Collection<Object[]> data() { return Arrays.asList( new Object[][] { - {R.string.autofill_credit_card_delete_confirmation_title} + { + R.string.autofill_credit_card_delete_confirmation_title, + R.string.autofill_iban_delete_confirmation_title + } }); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java index 2ee7a878..6f16478 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -15,6 +15,7 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -2635,6 +2636,22 @@ 0.5f); } + @Test + public void testFolioAttached_ReattachAnimationSkipped_TabGroupIndicators() { + // Arrange + int tabCount = 6; + initializeTest(false, false, false, 0, tabCount); + groupTabs(0, 2); + StripLayoutHelper stripLayoutHelperSpy = spy(mStripLayoutHelper); + + // Start and stop reorder mode for tab drop. + stripLayoutHelperSpy.startReorderModeForTabDrop(10.f); + stripLayoutHelperSpy.stopReorderModeForTesting(); + + // Verify: folio reattachment animation does not run for tab drop. + verify(stripLayoutHelperSpy, never()).updateTabAttachState(any(), eq(true), notNull()); + } + private float calculateExpectedBottomIndicatorWidth( float tabWidth, float tabCount, StripLayoutGroupTitle groupTitle) { // (tabWidth - tabOverlap(28.f)) * tabCount + groupTitleWidth -
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java index 0ba61712..c9a85b3e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java
@@ -35,6 +35,7 @@ import org.robolectric.shadows.ShadowDialog; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Features; import org.chromium.base.test.util.Features.DisableFeatures; @@ -46,6 +47,7 @@ import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator.ContextMenuGroup; import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.browser_ui.widget.ContextMenuDialog; import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; @@ -66,10 +68,7 @@ /** Unit tests for the context menu. Use density=mdpi so the screen density is 1. */ @RunWith(BaseRobolectricTestRunner.class) -@DisableFeatures({ - ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES -}) +@DisableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU}) @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SYS_UI_MATCHES_ACTIVITY}) public class ContextMenuCoordinatorTest { private static final int TOP_CONTENT_OFFSET_PX = 17; @@ -302,13 +301,11 @@ @Test @DisabledTest(message = "crbug.com/1444964") - @EnableFeatures({ - ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES - }) + @EnableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU}) @Config( shadows = {ShadowContextMenuDialog.class}, qualifiers = "mdpi") + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void testCreateContextMenuDialog_PopupStyle() { ContextMenuDialog dialog = createContextMenuDialogForTest(/* isPopup= */ true); ShadowContextMenuDialog shadowDialog = (ShadowContextMenuDialog) Shadow.extract(dialog); @@ -406,10 +403,7 @@ @Test @DisabledTest(message = "crbug.com/1444964") - @EnableFeatures({ - ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, - ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES - }) + @EnableFeatures({ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU}) @Config( shadows = { ShadowContextMenuDialog.class, @@ -417,6 +411,7 @@ ShadowProfile.class }, qualifiers = "mdpi") + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void testDisplayMenu_DragEnabled() { final int shadowImgWidth = 50; final int shadowImgHeight = 40;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsUnitTest.java index 841c8a1..137b75f 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsUnitTest.java
@@ -12,24 +12,19 @@ import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.flags.ChromeSwitches; /** Unit tests for {@link ContextMenuUtils}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(sdk = Build.VERSION_CODES.O) public class ContextMenuUtilsUnitTest { - @Rule public TestRule featureProcessor = new Features.JUnitProcessor(); Activity mActivity; @@ -44,21 +39,20 @@ } @Test - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES}) @Config(qualifiers = "sw320dp") + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void usePopupAllScreen_Small() { doTestUsePopupWhenEnabledByFlag(); } @Test - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES}) @Config(qualifiers = "sw600dp") + @CommandLineFlags.Add(ChromeSwitches.FORCE_CONTEXT_MENU_POPUP) public void usePopupAllScreen_Large() { doTestUsePopupWhenEnabledByFlag(); } @Test - @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES}) @Config(qualifiers = "sw320dp") public void doNotUsePopupForSmallScreen() { assertFalse( @@ -67,7 +61,6 @@ } @Test - @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES}) @Config(qualifiers = "sw600dp") public void usePopupForLargeScreen() { assertTrue( @@ -85,7 +78,7 @@ private void doTestUsePopupWhenEnabledByFlag() { assertTrue( - "Popup should be used when CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES enabled.", + "Popup should be used when switch FORCE_CONTEXT_MENU_POPUP is enabled.", ContextMenuUtils.usePopupContextMenuForContext(mActivity)); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java index 12fde1b45..b543a21 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
@@ -530,25 +530,6 @@ @Test public void - testCookieControlsIcon_trackingProtectionsEnabled_cookieBlockingEnabled_displaysReminderIPH() { - verify(mAnimationDelegate, never()).updateSecurityButton(anyInt()); - - mLocationBar.onHighlightCookieControl(true); - mLocationBar.onStatusChanged( - /* controls_visible= */ true, - /* protections_on= */ true, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.LIMITED, - /* expiration= */ 0); - - // Should show only the reminder IPH. - mLocationBar.onPageLoadStopped(); - verify(mPageInfoIPHController, never()).showCookieControlsIPH(anyInt(), anyInt()); - verify(mPageInfoIPHController, times(1)).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - public void testCookieControlsIcon_trackingProtectionsEnabled_cookieBlockingDisabled_doesNotDisplayIPH() { verify(mAnimationDelegate, never()).updateSecurityButton(anyInt()); @@ -563,7 +544,6 @@ // None of the IPHs should be shown. mLocationBar.onPageLoadStopped(); verify(mPageInfoIPHController, never()).showCookieControlsIPH(anyInt(), anyInt()); - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); } @Test @@ -582,7 +562,6 @@ // Should show only the Cookie controls IPH. mLocationBar.onPageLoadStopped(); verify(mPageInfoIPHController, times(1)).showCookieControlsIPH(anyInt(), anyInt()); - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); } private void assertUrlAndTitleVisible(boolean titleVisible, boolean urlVisible) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java index d45040e0..762bece 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java
@@ -36,6 +36,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.quickactionsearchwidget.QuickActionSearchWidgetProvider.QuickActionSearchWidgetProviderDino; import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityPreferencesManager.SearchActivityPreferences; +import org.chromium.url.GURL; import java.util.ArrayList; import java.util.Arrays; @@ -69,7 +70,7 @@ mOptionsWidgetB = new Bundle(); mPreferences = new SearchActivityPreferences( - "Search Engine", "https://search.engine.com", true, true, true); + "Search Engine", new GURL("https://search.engine.com"), true, true, true); // Inflate an actual RemoteViews to avoid stubbing internal methods or making // any other assumptions about the class.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java new file mode 100644 index 0000000..b74153bb --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/BottomAttachedUiObserverTest.java
@@ -0,0 +1,86 @@ +// Copyright 2024 The Chromium Authors +// 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.tabbed_mode; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import android.graphics.Color; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; + +@RunWith(BaseRobolectricTestRunner.class) +public class BottomAttachedUiObserverTest { + + private BottomAttachedUiObserver mBottomAttachedUiObserver; + private MockColorChangeObserver mColorChangeObserver; + @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mBottomAttachedUiObserver = new BottomAttachedUiObserver(mBrowserControlsStateProvider); + mColorChangeObserver = new MockColorChangeObserver(); + mBottomAttachedUiObserver.addObserver(mColorChangeObserver); + } + + @Test + public void testAdaptsColorToBrowserControls() { + int bottomControlsHeight = 100; + + mColorChangeObserver.assertColor(null); + + // Show bottom controls. + mBottomAttachedUiObserver.onBottomControlsBackgroundColorChanged(Color.RED); + mBottomAttachedUiObserver.onBottomControlsHeightChanged(bottomControlsHeight, 0); + mColorChangeObserver.assertColor(Color.RED); + + // Scroll off bottom controls partway. + mBottomAttachedUiObserver.onControlsOffsetChanged(0, 0, bottomControlsHeight / 2, 0, false); + mColorChangeObserver.assertColor(Color.RED); + + // Scroll off bottom controls fully. + mBottomAttachedUiObserver.onControlsOffsetChanged(0, 0, bottomControlsHeight, 0, false); + mColorChangeObserver.assertColor(null); + + // Scroll bottom controls back. + mBottomAttachedUiObserver.onControlsOffsetChanged(0, 0, 0, 0, false); + mColorChangeObserver.assertColor(Color.RED); + + // Hide bottom controls. + mBottomAttachedUiObserver.onBottomControlsHeightChanged(0, 0); + mColorChangeObserver.assertColor(null); + } + + @Test + public void testDestroy() { + mBottomAttachedUiObserver.destroy(); + verify(mBrowserControlsStateProvider).removeObserver(eq(mBottomAttachedUiObserver)); + } + + private static class MockColorChangeObserver implements BottomAttachedUiObserver.Observer { + private @Nullable @ColorInt Integer mColor; + + @Override + public void onBottomAttachedColorChanged(@Nullable Integer color) { + mColor = color; + } + + public void assertColor(@Nullable @ColorInt Integer expectedColor) { + assertEquals("Incorrect bottom attached color.", expectedColor, mColor); + } + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerUnitTest.java index 7619c51..715df17 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerUnitTest.java
@@ -28,6 +28,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.layouts.LayoutManager; @@ -49,6 +50,7 @@ @Mock private FullscreenManager mFullscreenManager; private ObservableSupplierImpl<EdgeToEdgeController> mEdgeToEdgeControllerObservableSupplier; @Mock private EdgeToEdgeController mEdgeToEdgeController; + @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider; @Mock private Tab mTab; @Before @@ -75,7 +77,8 @@ mTabModelSelector, mLayoutManagerSupplier, mFullscreenManager, - mEdgeToEdgeControllerObservableSupplier); + mEdgeToEdgeControllerObservableSupplier, + mBrowserControlsStateProvider); mLayoutManagerSupplier.set(mLayoutManager); mEdgeToEdgeControllerObservableSupplier.set(mEdgeToEdgeController); } @@ -106,6 +109,40 @@ } @Test + public void testMatchBottomAttachedColor() { + ChromeFeatureList.sNavBarColorMatchesTabBackground.setForTesting(true); + when(mTab.getBackgroundColor()).thenReturn(Color.BLUE); + when(mLayoutManager.getActiveLayoutType()).thenReturn(LayoutType.BROWSING); + mNavColorController.updateActiveTabForTesting(); + + mNavColorController.onBottomAttachedColorChanged(Color.RED); + assertTrue( + "Should be using the bottom attached UI color.", + mNavColorController.getUseBottomAttachedUiColorForTesting()); + assertEquals( + "The nav bar color should be the bottom attached UI color.", + Color.RED, + mNavColorController.getNavigationBarColorForTesting()); + assertEquals( + "The nav bar divider color should be the bottom attached UI color.", + Color.RED, + mNavColorController.getNavigationBarDividerColor(false)); + + mNavColorController.onBottomAttachedColorChanged(null); + assertFalse( + "Should no longer be using the bottom attached UI color.", + mNavColorController.getUseBottomAttachedUiColorForTesting()); + assertEquals( + "The nav bar color should match the tab background.", + Color.BLUE, + mNavColorController.getNavigationBarColorForTesting()); + assertEquals( + "The nav bar divider color should match the tab background.", + Color.BLUE, + mNavColorController.getNavigationBarDividerColor(false)); + } + + @Test public void testToEdgeDoesntMatchTabBackgroundColor() { ChromeFeatureList.sNavBarColorMatchesTabBackground.setForTesting(true); when(mTab.getBackgroundColor()).thenReturn(Color.BLUE);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 209ae97..d94dc09 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3368,12 +3368,14 @@ <message name="IDS_DOWNLOAD_BUBBLE_TOOLTIP_IN_PROGRESS_COUNT" desc="Tooltip text for the download toolbar button, displayed when there are one or more downloads in progress."> {COUNT, plural, =1 {1 download in progress} other {# downloads in progress}} </message> - <message name="IDS_DOWNLOAD_ROW_ESB_PROMOTION" desc="Link button text that teaches the user about Enhanced Protection."> - Discover enhanced protection to get Chrome's highest level of security for downloads - </message> - <message name="IDS_DOWNLOAD_ROW_ESB_PROMO_A11Y" desc="ARIA (accessibility) label describing a link which opens in a new tab."> - Opens security settings page in a new tab - </message> + <if expr="_google_chrome"> + <message name="IDS_DOWNLOAD_ROW_ESB_PROMOTION" desc="Link button text that teaches the user about Enhanced Protection."> + Discover enhanced protection to get Chrome's highest level of security for downloads + </message> + <message name="IDS_DOWNLOAD_ROW_ESB_PROMO_A11Y" desc="ARIA (accessibility) label describing a link which opens in a new tab."> + Opens security settings page in a new tab + </message> + </if> <!-- Tailored Warning in Download Bubble --> <message name="IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_WARNING_COOKIE_THEFT" @@ -4131,15 +4133,6 @@ <message name="IDS_COOKIE_CONTROLS_PROMO_SEE_HOW_BUTTON_TEXT" desc="Text on the button that opens the cookie controls bubble on the in-product-help bubble shown for the cookie controls bubble. Encourages users to see how to temporarily enable third-party cookies."> See how </message> - <message name="IDS_3PCD_USER_BYPASS_PROMO_TITLE" desc="Title of the in-product-help bubble shown for the user bypass feature. Reminds the user that tracking protection is on."> - Reminder: Tracking Protection is on - </message> - <message name="IDS_3PCD_USER_BYPASS_PROMO_TEXT" desc="Text on the in-product-help bubble shown for the user bypass feature. Explains that if a site is broken, enabling third-party cookies for the site might fix it."> - If a site you visit isn't working as expected, try temporarily allowing third-party cookies for that site. That will mean less protection but site features are more likely to work as expected. - </message> - <message name="IDS_3PCD_USER_BYPASS_PROMO_SCREENREADER" desc="Text announced with the in-product-help bubble shown for the user bypass feature. Explains how to temporarily enable third-party cookies if a site isn't working."> - If a site isn't working as expected, you can enable third-party cookies for it through the Tracking Protection option in the address bar. - </message> <!-- Win certificate selector dialog strings. --> <if expr="toolkit_views"> @@ -8348,9 +8341,15 @@ <message name="IDS_NTP_MODULES_GOOGLE_CALENDAR_TITLE" desc="Title of the Google Calendar module shown in various UIs for Customize Chrome and the NTP." meaning="Title of feature for showing a glimpse of a user's Google Calendar."> Google Calendar </message> + <message name="IDS_NTP_MODULES_GOOGLE_CALENDAR_DISABLE_BUTTON_TEXT" desc="Text shown on the disable button of a NTP Google Calendar card." translateable="false"> + Don't show Google Calendar + </message> <message name="IDS_NTP_MODULES_OUTLOOK_CALENDAR_TITLE" desc="Title of the Google Calendar module shown in various UIs for Customize Chrome and the NTP." meaning="Title of feature for showing a glimpse of a user's Google Calendar."> Outlook Calendar </message> + <message name="IDS_NTP_MODULES_OUTLOOK_CALENDAR_DISABLE_BUTTON_TEXT" desc="Text shown on the disable button of a NTP Outlook Calendar card." translateable="false"> + Don't show Outlook Calendar + </message> <message name="IDS_NTP_MODULES_PHOTOS_TITLE" desc="Title shown in the header of the photos module."> From your Google Photos </message> @@ -9094,11 +9093,20 @@ <message name="IDS_READING_MODE_PLAY_DESCRIPTION" desc="Accessibility description for button that plays speech in Read Aloud." translateable="false"> Listen to the text with natural voice </message> - <message name="IDS_READING_MODE_PLAY_SPEECH" desc="Accessibility label for button that plays speech in Read Aloud." translateable="false"> - Play + <message name="IDS_READING_MODE_PLAY_SPEECH" desc="Accessible name for button that plays speech in Read Aloud." translateable="false"> + Play keyboard shortcut k </message> - <message name="IDS_READING_MODE_PAUSE_SPEECH" desc="Accessibility label for button that pauses speech in Read Aloud." translateable="false"> - Pause + <message name="IDS_READING_MODE_PAUSE_SPEECH" desc="Accessibile name for button that pauses speech in Read Aloud." translateable="false"> + Pause keyboard shortcut k + </message> + <message name="IDS_READING_MODE_PLAY_TOOLTIP" desc="Tooltip label for button that plays speech in Read Aloud." translateable="false"> + Play (k) + </message> + <message name="IDS_READING_MODE_PAUSE_TOOLTIP" desc="Tooltip label for button that pauses speech in Read Aloud." translateable="false"> + Pause (k) + </message> + <message name="IDS_READING_MODE_STOP_SPEECH" desc="Accessibility label for button that stops speech in Read Aloud." translateable="false"> + Stop </message> <message name="IDS_READING_MODE_NAVIGATE_PREVIOUS_SENTENCE" desc="Accessibility label for button that moves speech in Read Aloud to the previous sentence." translateable="false"> Previous sentence @@ -9115,6 +9123,21 @@ <message name="IDS_READING_MODE_VOICE_SELECTION" desc="Accessibility label for button that opens a dropdown with options for changing the voice used for Read Aloud." translateable="false"> Voice selection </message> + <message name="IDS_READING_MODE_LANGUAGE_MENU" desc="Label for a button that opens a dialog with options for managing language preferences for Read Aloud." translateable="false"> + Languages... + </message> + <message name="IDS_READING_MODE_LANGUAGE_MENU_TITLE" desc="Dialog title label for a dialog with options for managing language preferences for Read Aloud." translateable="false"> + Languages + </message> + <message name="IDS_READING_MODE_LANGUAGE_MENU_CLOSE" desc="Label for a button to close a dialog with options for managing language preferences for Read Aloud." translateable="false"> + Close + </message> + <message name="IDS_READING_MODE_LANGUAGE_MENU_SEARCH_LABEL" desc="Label for a search field that searches for language preference to be managed for Read Aloud." translateable="false"> + Search + </message> + <message name="IDS_READING_MODE_LANGUAGE_MENU_SEARCH_CLEAR" desc="Accessibility label for a button to clear search field that searches for language preference to be managed for Read Aloud." translateable="false"> + Clear search + </message> <message name="IDS_READING_MODE_SIDE_PANEL_PROMO" desc="Text for the in-product-help bubble shown for the reading mode bubble."> To show a simplified view of this page, open the side panel and select Reading mode @@ -10961,7 +10984,7 @@ Dismiss </message> <message name="IDS_TAB_ORGANIZATION_NEW_TABS" desc="The label for the new badge divider in the tab organization results state"> - NEW TABS + New Tabs </message> <message name="IDS_TAB_ORGANIZATION_NOT_STARTED_TITLE" desc="The header text for the not started state in the tab organization UI"> Check if tabs can be organized
diff --git a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_SCREENREADER.png.sha1 b/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_SCREENREADER.png.sha1 deleted file mode 100644 index 745d1327..0000000 --- a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_SCREENREADER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -abdd3f0074be06432f20ec4e8e7a620f21f7ec76 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TEXT.png.sha1 deleted file mode 100644 index 2a8c96c..0000000 --- a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TEXT.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -fe24d071fff774c515246f6680814e9d3d05ec73 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TITLE.png.sha1 deleted file mode 100644 index eb3d067..0000000 --- a/chrome/app/generated_resources_grd/IDS_3PCD_USER_BYPASS_PROMO_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -7c249318e3c5c4c488733147070e47b82cf6ccff \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_SPEECH.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_SPEECH.png.sha1 index 5cd0747..7cf87b5f 100644 --- a/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_SPEECH.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_SPEECH.png.sha1
@@ -1 +1 @@ -2fdbcc936a34ca4910b703384322ddc6c9156e5c \ No newline at end of file +2a94f350cabc148d4da08ac580810cd4ea3fe1dd \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_TOOLTIP.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_TOOLTIP.png.sha1 new file mode 100644 index 0000000..8caa2f37 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_PAUSE_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +f9e4a7cf6d148e39e05388aa92d3055f909bc08d \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_SPEECH.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_SPEECH.png.sha1 index 4a97ce9..0c5fb030 100644 --- a/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_SPEECH.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_SPEECH.png.sha1
@@ -1 +1 @@ -ed6aaefe41e32223c3cb05e0dd7da1b7d72a262b \ No newline at end of file +08243911e5091f707cde4640e9a0924680a25aee \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_TOOLTIP.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_TOOLTIP.png.sha1 new file mode 100644 index 0000000..a3c0bee --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_PLAY_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +e94a88f7ba5746891d377be3894036468e4074bb \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_STOP_SPEECH.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_STOP_SPEECH.png.sha1 new file mode 100644 index 0000000..b15ff4c --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_STOP_SPEECH.png.sha1
@@ -0,0 +1 @@ +96f87eb4dc24a1fc7904c2497ca3e5ebbc328f7f \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NEW_TABS.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NEW_TABS.png.sha1 index f45d55a..5efcb00 100644 --- a/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NEW_TABS.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_TAB_ORGANIZATION_NEW_TABS.png.sha1
@@ -1 +1 @@ -00d3947b318bae0664b572a4c70959a285f77da0 \ No newline at end of file +b463883a662a60badb849063d4eb6d310fdbd971 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 73cba193..580947a 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -1411,23 +1411,16 @@ <message name="IDS_SETTINGS_ACCESSIBILITY_REDUCED_ANIMATIONS_DESCRIPTION" desc="Description for a checkbox which enables reduced animations."> Limit movement on the screen </message> - <!-- TODO(b:259374492): Mark these strings translatable before launch. --> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_LABEL" desc="The label for a drop-down menu that allows users to pick the blink rate of their text insertion caret." translateable="false"> - Text caret blink rate + <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_LABEL" desc="The label for a slider that allows users to pick the blink rate of their text insertion cursor."> + Text cursor blink rate </message> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION" desc="The description for a drop-down menu that allows users to pick the blink rate of their text insertion caret." translateable="false"> - Change the blink rate of the text caret in most text fields. + <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION" desc="The description for a slider that allows users to pick the blink rate of their text insertion cursor, explaining that they may need to restart apps for the setting to take effect."> + You may need to restart your apps for cursor changes to take effect </message> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF" desc="The name of a drop-down menu item that turns off the caret blink rate (so the caret is always steady on)." translateable="false"> - Do not blink + <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF" desc="The label for the minimum value on a slider that turns off the caret blink rate (so the caret is always steady on)."> + Off </message> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_NORMAL" desc="The name of a drop-down menu item that makes the caret blink at the normal rate." translateable="false"> - Normal - </message> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_SLOW" desc="The name of a drop-down menu item that makes the caret blink rate slower than normal." translateable="false"> - Slow - </message> - <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST" desc="The name of a drop-down menu item that makes the caret blink rate faster than normal." translateable="false"> + <message name="IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST" desc="The label for the maximum value on a slider that makes the caret blink rate faster than normal."> Fast </message> <message name="IDS_SETTINGS_STICKY_KEYS_LABEL" desc="Label for checkbox which enables sticky keys, with an explanation of the term 'sticky keys'.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..eb956b6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +31ed79a16b74b7f6e54533203ff5c336da757ece \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST.png.sha1 new file mode 100644 index 0000000..eb956b6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST.png.sha1
@@ -0,0 +1 @@ +31ed79a16b74b7f6e54533203ff5c336da757ece \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_LABEL.png.sha1 new file mode 100644 index 0000000..eb956b6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_LABEL.png.sha1
@@ -0,0 +1 @@ +31ed79a16b74b7f6e54533203ff5c336da757ece \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF.png.sha1 new file mode 100644 index 0000000..eb956b6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF.png.sha1
@@ -0,0 +1 @@ +31ed79a16b74b7f6e54533203ff5c336da757ece \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index d664642..b2cc660 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2860,6 +2860,8 @@ "android/contextualsearch/unhandled_tap_notifier_impl.h", "android/contextualsearch/unhandled_tap_web_contents_observer.cc", "android/contextualsearch/unhandled_tap_web_contents_observer.h", + "android/cookies/cookies_fetcher_restore_util.cc", + "android/cookies/cookies_fetcher_restore_util.h", "android/cookies/cookies_fetcher_util.cc", "android/customtabs/chrome_origin_verifier.cc", "android/customtabs/chrome_origin_verifier.h", @@ -5069,8 +5071,6 @@ "nearby_sharing/metrics/throughput_metric_logger.h", "nearby_sharing/nearby_confirmation_manager.cc", "nearby_sharing/nearby_confirmation_manager.h", - "nearby_sharing/nearby_connections_manager_impl.cc", - "nearby_sharing/nearby_connections_manager_impl.h", "nearby_sharing/nearby_notification_delegate.h", "nearby_sharing/nearby_notification_handler.cc", "nearby_sharing/nearby_notification_handler.h", @@ -5259,6 +5259,8 @@ "task_manager/providers/vm/vm_process_task_provider.h", "task_manager/sampling/arc_shared_sampler.cc", "task_manager/sampling/arc_shared_sampler.h", + "ui/ash/shelf/chrome_shelf_metrics_provider.cc", + "ui/ash/shelf/chrome_shelf_metrics_provider.h", "upgrade_detector/installed_version_updater_chromeos.cc", "upgrade_detector/installed_version_updater_chromeos.h", "upgrade_detector/upgrade_detector_chromeos.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 5844bf9d..f9ba10e 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -94,6 +94,7 @@ #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/feature_list.h" #include "components/feed/feed_feature_list.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/flags_ui/feature_entry.h" #include "components/flags_ui/feature_entry_macros.h" #include "components/flags_ui/flags_state.h" @@ -188,6 +189,7 @@ #include "device/vr/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h" #include "flag_descriptions.h" +#include "gpu/command_buffer/client/client_shared_image.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_switches.h" #include "media/audio/audio_features.h" @@ -6336,13 +6338,6 @@ SINGLE_VALUE_TYPE(history_clusters::switches:: kShouldShowAllClustersOnProminentUiSurfaces)}, - {"history-journeys-include-synced-visits", - flag_descriptions::kJourneysIncludeSyncedVisitsName, - flag_descriptions::kJourneysIncludeSyncedVisitsDescription, - kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE( - history_clusters::internal::kJourneysIncludeSyncedVisits)}, - {"history-journeys-zero-state-filtering", flag_descriptions::kJourneysZeroStateFilteringName, flag_descriptions::kJourneysZeroStateFilteringDescription, @@ -6933,12 +6928,6 @@ "")}, #endif - {"legacy-tech-report-enable-cookie-issue-reports", - flag_descriptions::kLegacyTechReportEnableCookieIssueReportsName, - flag_descriptions::kLegacyTechReportEnableCookieIssueReportsDescription, - kOsAll, - FEATURE_VALUE_TYPE(features::kLegacyTechReportEnableCookieIssueReports)}, - { "zero-copy-tab-capture", flag_descriptions::kEnableZeroCopyTabCaptureName, @@ -6963,6 +6952,12 @@ {"pdf-use-skia-renderer", flag_descriptions::kPdfUseSkiaRendererName, flag_descriptions::kPdfUseSkiaRendererDescription, kOsDesktop, FEATURE_VALUE_TYPE(chrome_pdf::features::kPdfUseSkiaRenderer)}, + +#if BUILDFLAG(ENABLE_PDF_INK2) + {"pdf-ink2", flag_descriptions::kPdfInk2Name, + flag_descriptions::kPdfInk2Description, kOsDesktop, + FEATURE_VALUE_TYPE(chrome_pdf::features::kPdfInk2)}, +#endif // BUILDFLAG(ENABLE_PDF_INK2) #endif // BUILDFLAG(ENABLE_PDF) #if BUILDFLAG(ENABLE_PRINTING) @@ -8243,10 +8238,6 @@ flag_descriptions::kShimlessRMAComplianceCheckName, flag_descriptions::kShimlessRMAComplianceCheckDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kShimlessRMAComplianceCheck)}, - {"shimless-rma-sku-description", - flag_descriptions::kShimlessRMASkuDescriptionName, - flag_descriptions::kShimlessRMASkuDescriptionDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kShimlessRMASkuDescription)}, {"nearby-sharing-self-share", flag_descriptions::kNearbySharingSelfShareName, flag_descriptions::kNearbySharingSelfShareDescription, kOsCrOS, @@ -8996,6 +8987,11 @@ {"local-printer-observing", flag_descriptions::kLocalPrinterObservingName, flag_descriptions::kLocalPrinterObservingDescription, kOsCrOS | kOsLacros, FEATURE_VALUE_TYPE(features::kLocalPrinterObserving)}, + {"print-preview-cros-primary", + flag_descriptions::kPrintPreviewCrosPrimaryName, + flag_descriptions::kPrintPreviewCrosPrimaryDescription, + kOsCrOS | kOsLacros, + FEATURE_VALUE_TYPE(features::kPrintPreviewCrosPrimary)}, {"print-preview-setup-assistance", flag_descriptions::kPrintPreviewSetupAssistanceName, flag_descriptions::kPrintPreviewSetupAssistanceDescription, @@ -9765,12 +9761,6 @@ FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardArtImage)}, #if BUILDFLAG(IS_ANDROID) - {"context-menu-popup-for-all-screen-sizes", - flag_descriptions::kContextMenuPopupForAllScreenSizesName, - flag_descriptions::kContextMenuPopupForAllScreenSizesDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kContextMenuPopupForAllScreenSizes)}, - {"tab-group-pane-android", flag_descriptions::kTabGroupPaneAndroidName, flag_descriptions::kTabGroupPaneAndroidDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kTabGroupPaneAndroid)}, @@ -9779,6 +9769,11 @@ flag_descriptions::kTabGroupParityAndroidDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kTabGroupParityAndroid)}, + {"tab-strip-group-collapse-android", + flag_descriptions::kTabStripGroupCollapseAndroidName, + flag_descriptions::kTabStripGroupCollapseAndroidDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kTabStripGroupCollapseAndroid)}, + {"tab-strip-group-indicators-android", flag_descriptions::kTabStripGroupIndicatorsAndroidName, flag_descriptions::kTabStripGroupIndicatorsAndroidDescription, kOsAndroid, @@ -9953,6 +9948,11 @@ flag_descriptions::kUseMultiPlaneFormatForSoftwareVideoDescription, kOsAll, FEATURE_VALUE_TYPE(media::kUseMultiPlaneFormatForSoftwareVideo)}, + {"enable-automatic-shared-image-management", + flag_descriptions::kEnableAutomaticSharedImageManagementName, + flag_descriptions::kEnableAutomaticSharedImageManagementDescription, + kOsAll, FEATURE_VALUE_TYPE(gpu::kEnableAutomaticSharedImageManagement)}, + #if BUILDFLAG(IS_CHROMEOS_ASH) {"enable-notification-image-drag", flag_descriptions::kEnableNotificationImageDragName, @@ -10291,6 +10291,9 @@ {"drive-fs-show-cse-files", flag_descriptions::kDriveFsShowCSEFilesName, flag_descriptions::kDriveFsShowCSEFilesDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kDriveFsShowCSEFiles)}, + {"drive-fs-mirroring", flag_descriptions::kDriveFsMirroringName, + flag_descriptions::kDriveFsShowCSEFilesDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kDriveFsMirroring)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -11091,7 +11094,8 @@ flag_descriptions::kEnableFingerprintingProtectionBlocklistName, flag_descriptions::kEnableFingerprintingProtectionBlocklistDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kEnableFingerprintingProtectionBlocklist)}, + FEATURE_VALUE_TYPE(fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter)}, #if BUILDFLAG(IS_WIN) {"authenticate-using-new-windows-hello-api",
diff --git a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler.cc b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler.cc index b557798..45726c9 100644 --- a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler.cc +++ b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler.cc
@@ -394,7 +394,7 @@ content::RenderFrameHost* AXMediaAppUntrustedHandler::GetMediaAppRenderFrameHost() const { content::WebContents* web_contents = GetMediaAppWebContents(); - return web_contents ? web_contents->GetFocusedFrame() : nullptr; + return web_contents ? web_contents->GetPrimaryMainFrame() : nullptr; } ui::AXNodeID AXMediaAppUntrustedHandler::GetMediaAppRootNodeID() const {
diff --git a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_browsertest.cc b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_browsertest.cc index ac05e3c..3341d18 100644 --- a/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_browsertest.cc +++ b/chrome/browser/accessibility/media_app/ax_media_app_untrusted_handler_browsertest.cc
@@ -85,7 +85,6 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - browser()->tab_strip_model()->GetActiveWebContents()->Focus(); ASSERT_NE(nullptr, AXMediaAppHandlerFactory::GetInstance()); mojo::PendingRemote<ash::media_app_ui::mojom::OcrUntrustedPage> pageRemote; mojo::PendingReceiver<ash::media_app_ui::mojom::OcrUntrustedPage>
diff --git a/chrome/browser/android/cookies/cookies_fetcher_restore_util.cc b/chrome/browser/android/cookies/cookies_fetcher_restore_util.cc new file mode 100644 index 0000000..1f87e39 --- /dev/null +++ b/chrome/browser/android/cookies/cookies_fetcher_restore_util.cc
@@ -0,0 +1,104 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/cookies/cookies_fetcher_restore_util.h" + +#include "base/time/time.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "content/public/browser/storage_partition.h" +#include "net/cookies/cookie_partition_key.h" +#include "net/cookies/cookie_util.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" + +namespace cookie_fetcher_restore_util { + +// Returns the cookie service at the client end of the mojo pipe. +network::mojom::CookieManager* GetCookieServiceClient() { + // Since restoring Incognito CCT session from cookies is not supported, it is + // safe to use the primary OTR profile here. + return ProfileManager::GetPrimaryUserProfile() + ->GetPrimaryOTRProfile(/*create_if_needed=*/true) + ->GetDefaultStoragePartition() + ->GetCookieManagerForBrowserProcess(); +} + +void CookiesFetcherRestoreCookiesImpl( + JNIEnv* env, + const jni_zero::JavaParamRef<jstring>& name, + const jni_zero::JavaParamRef<jstring>& value, + const jni_zero::JavaParamRef<jstring>& domain, + const jni_zero::JavaParamRef<jstring>& path, + jlong creation, + jlong expiration, + jlong last_access, + jlong last_update, + jboolean secure, + jboolean httponly, + jint same_site, + jint priority, + const jni_zero::JavaParamRef<jstring>& partition_key, + jint source_scheme, + jint source_port, + jint source_type) { + if (!ProfileManager::GetPrimaryUserProfile()->HasPrimaryOTRProfile()) { + return; // Don't create it. There is nothing to do. + } + + std::string domain_str(base::android::ConvertJavaStringToUTF8(env, domain)); + std::string path_str(base::android::ConvertJavaStringToUTF8(env, path)); + + std::string top_level_site = + base::android::ConvertJavaStringToUTF8(env, partition_key); + // TODO (crbug.com/326605834) Once ancestor chain bit changes are + // implemented update this method utilize the ancestor bit. + base::expected<std::optional<net::CookiePartitionKey>, std::string> + serialized_cookie_partition_key = net::CookiePartitionKey::FromStorage( + top_level_site, /*has_cross_site_ancestor=*/true); + if (!serialized_cookie_partition_key.has_value()) { + return; + } + + std::unique_ptr<net::CanonicalCookie> cookie = + net::CanonicalCookie::FromStorage( + base::android::ConvertJavaStringToUTF8(env, name), + base::android::ConvertJavaStringToUTF8(env, value), domain_str, + path_str, + base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(creation)), + base::Time::FromDeltaSinceWindowsEpoch( + base::Microseconds(expiration)), + base::Time::FromDeltaSinceWindowsEpoch( + base::Microseconds(last_access)), + base::Time::FromDeltaSinceWindowsEpoch( + base::Microseconds(last_update)), + secure, httponly, static_cast<net::CookieSameSite>(same_site), + static_cast<net::CookiePriority>(priority), + serialized_cookie_partition_key.value(), + static_cast<net::CookieSourceScheme>(source_scheme), source_port, + static_cast<net::CookieSourceType>(source_type)); + // FromStorage() uses a less strict version of IsCanonical(), we need to check + // the stricter version as well here. This is safe because this function is + // only used for incognito cookies which don't survive Chrome updates and + // therefore should never be the "older" less strict variety. + if (!cookie || !cookie->IsCanonical()) { + return; + } + + // Assume HTTPS - since the cookies are being restored from another store, + // they have already gone through the strict secure check. + // + // Similarly, permit samesite cookies to be imported. + net::CookieOptions options; + options.set_include_httponly(); + options.set_same_site_cookie_context( + net::CookieOptions::SameSiteCookieContext::MakeInclusive()); + options.set_do_not_update_access_time(); + GetCookieServiceClient()->SetCanonicalCookie( + *cookie, + net::cookie_util::CookieDomainAndPathToURL( + domain_str, path_str, + static_cast<net::CookieSourceScheme>(source_scheme)), + options, network::mojom::CookieManager::SetCanonicalCookieCallback()); +} + +} // namespace cookie_fetcher_restore_util
diff --git a/chrome/browser/android/cookies/cookies_fetcher_restore_util.h b/chrome/browser/android/cookies/cookies_fetcher_restore_util.h new file mode 100644 index 0000000..5e3c3c9 --- /dev/null +++ b/chrome/browser/android/cookies/cookies_fetcher_restore_util.h
@@ -0,0 +1,41 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_COOKIES_COOKIES_FETCHER_RESTORE_UTIL_H_ +#define CHROME_BROWSER_ANDROID_COOKIES_COOKIES_FETCHER_RESTORE_UTIL_H_ + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "services/network/public/mojom/cookie_manager.mojom-forward.h" + +namespace cookie_fetcher_restore_util { + +// Returns the cookie service at the client end of the mojo pipe. +network::mojom::CookieManager* GetCookieServiceClient(); + +// Creates and sets a canonical cookie for the off-the-record session (i.e. +// incognito mode). It is a no-op for the standard session. Typically associated +// with the #onResume of Android's activity lifecycle. +void CookiesFetcherRestoreCookiesImpl( + JNIEnv* env, + const jni_zero::JavaParamRef<jstring>& name, + const jni_zero::JavaParamRef<jstring>& value, + const jni_zero::JavaParamRef<jstring>& domain, + const jni_zero::JavaParamRef<jstring>& path, + jlong creation, + jlong expiration, + jlong last_access, + jlong last_update, + jboolean secure, + jboolean httponly, + jint same_site, + jint priority, + const jni_zero::JavaParamRef<jstring>& partition_key, + jint source_scheme, + jint source_port, + jint source_type); + +} // namespace cookie_fetcher_restore_util + +#endif // CHROME_BROWSER_ANDROID_COOKIES_COOKIES_FETCHER_RESTORE_UTIL_H_
diff --git a/chrome/browser/android/cookies/cookies_fetcher_restore_util_browsertest.cc b/chrome/browser/android/cookies/cookies_fetcher_restore_util_browsertest.cc new file mode 100644 index 0000000..1427f5e --- /dev/null +++ b/chrome/browser/android/cookies/cookies_fetcher_restore_util_browsertest.cc
@@ -0,0 +1,119 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/cookies/cookies_fetcher_restore_util.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/test/bind.h" +#include "base/test/gtest_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/tab/web_contents_state.h" +#include "chrome/test/base/android/android_browser_test.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_partition_key.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" + +namespace cookie_fetcher_restore_util { + +class CookiesFetcherRestoreUtilBrowserTest : public AndroidBrowserTest { + protected: + CookiesFetcherRestoreUtilBrowserTest() = default; + ~CookiesFetcherRestoreUtilBrowserTest() override = default; + + void Navigate() { + ASSERT_TRUE(content::NavigateToURL( + GetActiveWebContents(), + embedded_test_server()->GetURL("/android/google.html"))); + Profile::FromBrowserContext(GetActiveWebContents()->GetBrowserContext()) + ->GetPrimaryOTRProfile(/*create_if_needed=*/true); + } + + content::WebContents* GetActiveWebContents() { + return chrome_test_utils::GetActiveWebContents(this); + } + + void AddCookie(std::string partition_key) { + JNIEnv* env = base::android::AttachCurrentThread(); + CookiesFetcherRestoreCookiesImpl( + env, + jni_zero::JavaParamRef<jstring>( + env, base::android::ConvertUTF8ToJavaString(env, "test").obj()), + jni_zero::JavaParamRef<jstring>( + env, base::android::ConvertUTF8ToJavaString(env, "test").obj()), + jni_zero::JavaParamRef<jstring>( + env, + base::android::ConvertUTF8ToJavaString(env, "google.com").obj()), + jni_zero::JavaParamRef<jstring>( + env, base::android::ConvertUTF8ToJavaString(env, "/").obj()), + /*creation=*/0, /*expiration=*/0, /*last_access=*/0, + /*last_update=*/0, /*secure=*/true, /*httponly=*/false, + /*same_site=*/0, /*priority=*/0, + jni_zero::JavaParamRef<jstring>( + env, + base::android::ConvertUTF8ToJavaString(env, partition_key).obj()), + /*source_scheme=*/2, /*source_port=*/-1, /*source_type=*/0); + } + + bool HasCookie(std::string partition_key) { + net::CookieList cookies_for_profile; + { + base::RunLoop loop; + GetCookieServiceClient()->GetAllCookies( + base::BindLambdaForTesting([&](const net::CookieList& cookies) { + cookies_for_profile = cookies; + loop.Quit(); + })); + loop.Run(); + } + if (cookies_for_profile.size() == 0u) { + return false; + } + EXPECT_EQ(cookies_for_profile.size(), 1u); + EXPECT_EQ(cookies_for_profile[0].Name(), "test"); + EXPECT_EQ(cookies_for_profile[0].PartitionKey(), + *net::CookiePartitionKey::FromStorage( + partition_key, /*has_cross_site_ancestor=*/true)); + return true; + } + + private: + void SetUpOnMainThread() override { + ASSERT_TRUE(embedded_test_server()->Start()); + PlatformBrowserTest::SetUpOnMainThread(); + } +}; + +// A cookie with an empty partition key should be restorable. +IN_PROC_BROWSER_TEST_F(CookiesFetcherRestoreUtilBrowserTest, + EmptyPartitionKey) { + std::string partition_key = ""; + Navigate(); + AddCookie(partition_key); + EXPECT_TRUE(HasCookie(partition_key)); +} + +// A cookie with an SchemefulSite partition key should be restorable. +IN_PROC_BROWSER_TEST_F(CookiesFetcherRestoreUtilBrowserTest, + ValidPartitionKey) { + std::string partition_key = "https://google.com"; + Navigate(); + AddCookie(partition_key); + EXPECT_TRUE(HasCookie(partition_key)); +} + +// A cookie with a malformed partition key should not be restorable. +IN_PROC_BROWSER_TEST_F(CookiesFetcherRestoreUtilBrowserTest, + InvalidPartitionKey) { + std::string partition_key = "(╯°□°)╯︵ ┻━┻"; + Navigate(); + AddCookie(partition_key); + EXPECT_FALSE(HasCookie(partition_key)); +} + +} // namespace cookie_fetcher_restore_util
diff --git a/chrome/browser/android/cookies/cookies_fetcher_util.cc b/chrome/browser/android/cookies/cookies_fetcher_util.cc index 666d6a2..fc0aa9d 100644 --- a/chrome/browser/android/cookies/cookies_fetcher_util.cc +++ b/chrome/browser/android/cookies/cookies_fetcher_util.cc
@@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/functional/bind.h" #include "base/time/time.h" +#include "chrome/browser/android/cookies/cookies_fetcher_restore_util.h" #include "chrome/browser/profiles/android/jni_headers/CookiesFetcher_jni.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/browser_context.h" @@ -22,16 +23,6 @@ namespace { -// Returns the cookie service at the client end of the mojo pipe. -network::mojom::CookieManager* GetCookieServiceClient() { - // Since restoring Incognito CCT session from cookies is not supported, it is - // safe to use the primary OTR profile here. - return ProfileManager::GetPrimaryUserProfile() - ->GetPrimaryOTRProfile(/*create_if_needed=*/true) - ->GetDefaultStoragePartition() - ->GetCookieManagerForBrowserProcess(); -} - // Passes the fetched |cookies| to the application so that can be saved in a // file. void OnCookiesFetchFinished(const net::CookieList& cookies) { @@ -84,14 +75,11 @@ return; } - GetCookieServiceClient()->GetAllCookies( + cookie_fetcher_restore_util::GetCookieServiceClient()->GetAllCookies( base::BindOnce(&OnCookiesFetchFinished)); } -// Creates and sets a canonical cookie for the off-the-record session (i.e. -// incognito mode). It is a no-op for the standard session. Typically associated -// with the #onResume of Android's activty lifecycle. -static void JNI_CookiesFetcher_RestoreCookies( +void JNI_CookiesFetcher_RestoreCookies( JNIEnv* env, const JavaParamRef<jstring>& name, const JavaParamRef<jstring>& value, @@ -109,64 +97,8 @@ jint source_scheme, jint source_port, jint source_type) { - if (!ProfileManager::GetPrimaryUserProfile()->HasPrimaryOTRProfile()) - return; // Don't create it. There is nothing to do. - - std::string domain_str(base::android::ConvertJavaStringToUTF8(env, domain)); - std::string path_str(base::android::ConvertJavaStringToUTF8(env, path)); - - std::string top_level_site = - base::android::ConvertJavaStringToUTF8(env, partition_key); - if (top_level_site.empty()) { - return; - } - // TODO (crbug.com/326605834) Once ancestor chain bit changes are - // implemented update this method utilize the ancestor bit. - base::expected<net::CookiePartitionKey, std::string> - serialized_cookie_partition_key = - net::CookiePartitionKey::FromUntrustedInput( - top_level_site, /*has_cross_site_ancestor=*/true); - if (!serialized_cookie_partition_key.has_value()) { - return; - } - - std::unique_ptr<net::CanonicalCookie> cookie = - net::CanonicalCookie::FromStorage( - base::android::ConvertJavaStringToUTF8(env, name), - base::android::ConvertJavaStringToUTF8(env, value), domain_str, - path_str, - base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(creation)), - base::Time::FromDeltaSinceWindowsEpoch( - base::Microseconds(expiration)), - base::Time::FromDeltaSinceWindowsEpoch( - base::Microseconds(last_access)), - base::Time::FromDeltaSinceWindowsEpoch( - base::Microseconds(last_update)), - secure, httponly, static_cast<net::CookieSameSite>(same_site), - static_cast<net::CookiePriority>(priority), - serialized_cookie_partition_key.value(), - static_cast<net::CookieSourceScheme>(source_scheme), source_port, - static_cast<net::CookieSourceType>(source_type)); - // FromStorage() uses a less strict version of IsCanonical(), we need to check - // the stricter version as well here. This is safe because this function is - // only used for incognito cookies which don't survive Chrome updates and - // therefore should never be the "older" less strict variety. - if (!cookie || !cookie->IsCanonical()) - return; - - // Assume HTTPS - since the cookies are being restored from another store, - // they have already gone through the strict secure check. - // - // Similarly, permit samesite cookies to be imported. - net::CookieOptions options; - options.set_include_httponly(); - options.set_same_site_cookie_context( - net::CookieOptions::SameSiteCookieContext::MakeInclusive()); - options.set_do_not_update_access_time(); - GetCookieServiceClient()->SetCanonicalCookie( - *cookie, - net::cookie_util::CookieDomainAndPathToURL( - domain_str, path_str, - static_cast<net::CookieSourceScheme>(source_scheme)), - options, network::mojom::CookieManager::SetCanonicalCookieCallback()); + cookie_fetcher_restore_util::CookiesFetcherRestoreCookiesImpl( + env, name, value, domain, path, creation, expiration, last_access, + last_update, secure, httponly, same_site, priority, partition_key, + source_scheme, source_port, source_type); }
diff --git a/chrome/browser/android/favicon_helper_unittest.cc b/chrome/browser/android/favicon_helper_unittest.cc index 58cf8cde..c1a9c5131 100644 --- a/chrome/browser/android/favicon_helper_unittest.cc +++ b/chrome/browser/android/favicon_helper_unittest.cc
@@ -31,7 +31,7 @@ // Create bitmap and fill with |color|. scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); gfx::PNGCodec::EncodeBGRASkBitmap(gfx::test::CreateBitmap(size, color), false, - &data->data()); + &data->as_vector()); result.bitmap_data = data; result.pixel_size = gfx::Size(size, size);
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc index ae555d39..9d59913 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc +++ b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
@@ -35,8 +35,7 @@ IDR_APP_DEFAULT_ICON, apps_util::GetPrimaryDisplayUIScaleFactor()); base::RefCountedBytes* image_bytes = new base::RefCountedBytes(); - image_bytes->data().assign(contents.data(), - contents.data() + contents.size()); + image_bytes->as_vector().assign(contents.begin(), contents.end()); std::move(callback).Run(image_bytes); }
diff --git a/chrome/browser/apps/app_service/browser_app_instance_tracker.cc b/chrome/browser/apps/app_service/browser_app_instance_tracker.cc index f9372a9..03fb3df 100644 --- a/chrome/browser/apps/app_service/browser_app_instance_tracker.cc +++ b/chrome/browser/apps/app_service/browser_app_instance_tracker.cc
@@ -50,11 +50,22 @@ if (window1 == nullptr || window2 == nullptr) { return false; } - auto* host1 = views::DesktopWindowTreeHostLacros::From(window1->GetHost()); - auto* host2 = views::DesktopWindowTreeHostLacros::From(window2->GetHost()); + views::DesktopWindowTreeHostPlatform* host1 = + views::DesktopWindowTreeHostLacros::From(window1->GetHost()); + views::DesktopWindowTreeHostPlatform* host2 = + views::DesktopWindowTreeHostLacros::From(window2->GetHost()); + if (host1 == nullptr || host2 == nullptr) { return false; } else { + // If the host is a window_tree_host for bubble, the associated browser is + // up in the window_parent() chain. + while (host1->window_parent()) { + host1 = host1->window_parent(); + } + while (host2->window_parent()) { + host2 = host2->window_parent(); + } return host1 == host2; } }
diff --git a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc index fc3f4f96..44a386c 100644 --- a/chrome/browser/apps/app_service/metrics/app_service_metrics.cc +++ b/chrome/browser/apps/app_service/metrics/app_service_metrics.cc
@@ -213,78 +213,84 @@ namespace apps { -void RecordAppLaunch(const std::string& app_id, - apps::LaunchSource launch_source) { - if (const std::optional<apps::DefaultAppName> app_name = +std::optional<apps::DefaultAppName> AppIdToName(const std::string& app_id) { + if (const std::optional<DefaultAppName> app_name = PreinstalledWebAppIdToName(app_id)) { - RecordDefaultAppLaunch(app_name.value(), launch_source); - return; + return app_name; } #if BUILDFLAG(IS_CHROMEOS_ASH) - if (const std::optional<apps::DefaultAppName> app_name = + if (const std::optional<DefaultAppName> app_name = SystemWebAppIdToName(app_id)) { - RecordDefaultAppLaunch(app_name.value(), launch_source); - - if (ash::features::IsWelcomeTourEnabled()) { - RecordWelcomeTourInteraction(app_name.value(), launch_source); - } - - return; + return app_name; } #endif // BUILDFLAG(IS_CHROMEOS_ASH) if (app_id == extension_misc::kCalculatorAppId) { - // Launches of the legacy calculator chrome app. - RecordDefaultAppLaunch(DefaultAppName::kCalculatorChromeApp, launch_source); + // The legacy calculator chrome app. + return DefaultAppName::kCalculatorChromeApp; } else if (app_id == extension_misc::kTextEditorAppId) { - RecordDefaultAppLaunch(DefaultAppName::kText, launch_source); + return DefaultAppName::kText; } else if (app_id == app_constants::kChromeAppId) { - RecordDefaultAppLaunch(DefaultAppName::kChrome, launch_source); + return DefaultAppName::kChrome; } else if (app_id == extension_misc::kGoogleDocsAppId) { - RecordDefaultAppLaunch(DefaultAppName::kDocs, launch_source); + return DefaultAppName::kDocs; } else if (app_id == extension_misc::kGoogleDriveAppId) { - RecordDefaultAppLaunch(DefaultAppName::kDrive, launch_source); + return DefaultAppName::kDrive; #if BUILDFLAG(IS_CHROMEOS_ASH) } else if (app_id == arc::kGoogleDuoAppId) { - RecordDefaultAppLaunch(DefaultAppName::kDuo, launch_source); + return DefaultAppName::kDuo; } else if (app_id == extension_misc::kFilesManagerAppId) { - RecordDefaultAppLaunch(DefaultAppName::kFiles, launch_source); + return DefaultAppName::kFiles; } else if (app_id == extension_misc::kGmailAppId || app_id == arc::kGmailAppId) { - RecordDefaultAppLaunch(DefaultAppName::kGmail, launch_source); + return DefaultAppName::kGmail; #endif // BUILDFLAG(IS_CHROMEOS_ASH) } else if (app_id == extension_misc::kGoogleKeepAppId) { - RecordDefaultAppLaunch(DefaultAppName::kKeep, launch_source); + return DefaultAppName::kKeep; #if BUILDFLAG(IS_CHROMEOS_ASH) } else if (app_id == extension_misc::kGooglePhotosAppId || app_id == arc::kGooglePhotosAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPhotos, launch_source); + return DefaultAppName::kPhotos; } else if (app_id == arc::kPlayBooksAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPlayBooks, launch_source); + return DefaultAppName::kPlayBooks; } else if (app_id == arc::kPlayGamesAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPlayGames, launch_source); + return DefaultAppName::kPlayGames; } else if (app_id == arc::kPlayMoviesAppId || app_id == extension_misc::kGooglePlayMoviesAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPlayMovies, launch_source); + return DefaultAppName::kPlayMovies; } else if (app_id == arc::kPlayMusicAppId || app_id == extension_misc::kGooglePlayMusicAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPlayMusic, launch_source); + return DefaultAppName::kPlayMusic; } else if (app_id == arc::kPlayStoreAppId) { - RecordDefaultAppLaunch(DefaultAppName::kPlayStore, launch_source); + return DefaultAppName::kPlayStore; #endif // BUILDFLAG(IS_CHROMEOS_ASH) } else if (app_id == extension_misc::kGoogleSheetsAppId) { - RecordDefaultAppLaunch(DefaultAppName::kSheets, launch_source); + return DefaultAppName::kSheets; } else if (app_id == extension_misc::kGoogleSlidesAppId) { - RecordDefaultAppLaunch(DefaultAppName::kSlides, launch_source); + return DefaultAppName::kSlides; } else if (app_id == extensions::kWebStoreAppId) { - RecordDefaultAppLaunch(DefaultAppName::kWebStore, launch_source); + return DefaultAppName::kWebStore; #if BUILDFLAG(IS_CHROMEOS_ASH) } else if (app_id == extension_misc::kYoutubeAppId || app_id == arc::kYoutubeAppId) { - RecordDefaultAppLaunch(DefaultAppName::kYouTube, launch_source); + return DefaultAppName::kYouTube; } else if (app_id == arc::kGoogleTVAppId) { - RecordDefaultAppLaunch(DefaultAppName::kGoogleTv, launch_source); + return DefaultAppName::kGoogleTv; +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + } + + return std::nullopt; +} + +void RecordAppLaunch(const std::string& app_id, + apps::LaunchSource launch_source) { + if (const std::optional<DefaultAppName> app_name = AppIdToName(app_id)) { + RecordDefaultAppLaunch(app_name.value(), launch_source); +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (ash::features::IsWelcomeTourEnabled()) { + RecordWelcomeTourInteraction(app_name.value(), launch_source); + } #endif // BUILDFLAG(IS_CHROMEOS_ASH) } }
diff --git a/chrome/browser/apps/app_service/metrics/app_service_metrics.h b/chrome/browser/apps/app_service/metrics/app_service_metrics.h index aeafe50..bd7dca0 100644 --- a/chrome/browser/apps/app_service/metrics/app_service_metrics.h +++ b/chrome/browser/apps/app_service/metrics/app_service_metrics.h
@@ -92,6 +92,10 @@ kMaxValue = kReleaseNotes, }; +// Converts an app ID to the corresponding `DefaultAppName`, or nullopt if +// it doesn't match a known ID. +std::optional<apps::DefaultAppName> AppIdToName(const std::string& app_id); + void RecordAppLaunch(const std::string& app_id, apps::LaunchSource launch_source);
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 3526785..3a685a9 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -771,8 +771,6 @@ "borealis/borealis_window_manager.h", "borealis/infra/described.h", "borealis/infra/transition.h", - "browser_accelerator_configuration.cc", - "browser_accelerator_configuration.h", "browser_context_keyed_service_factories.cc", "browser_context_keyed_service_factories.h", "bruschetta/bruschetta_download.cc", @@ -3709,6 +3707,7 @@ "//ash/webui/camera_app_ui", "//ash/webui/common/mojom:sea_pen", "//ash/webui/connectivity_diagnostics", + "//ash/webui/diagnostics_ui", "//ash/webui/eche_app_ui", "//ash/webui/file_manager:file_manager_ui", "//ash/webui/files_internals", @@ -5514,7 +5513,6 @@ "borealis/borealis_window_manager_unittest.cc", "borealis/infra/described_unittest.cc", "borealis/infra/transition_unittest.cc", - "browser_accelerator_configuration_unittest.cc", "bruschetta/bruschetta_download_unittest.cc", "bruschetta/bruschetta_installer_impl_unittest.cc", "bruschetta/bruschetta_launcher_unittest.cc",
diff --git a/chrome/browser/ash/browser_accelerator_configuration.cc b/chrome/browser/ash/browser_accelerator_configuration.cc deleted file mode 100644 index 29a1d1d..0000000 --- a/chrome/browser/ash/browser_accelerator_configuration.cc +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ash/browser_accelerator_configuration.h" - -#include "ash/public/cpp/accelerator_configuration.h" -#include "ash/public/mojom/accelerator_configuration.mojom.h" -#include "ash/public/mojom/accelerator_keys.mojom.h" - -namespace ash { - -using ::ash::mojom::AcceleratorConfigResult; - -BrowserAcceleratorConfiguration::BrowserAcceleratorConfiguration() - : AcceleratorConfiguration(mojom::AcceleratorSource::kBrowser) {} - -BrowserAcceleratorConfiguration::~BrowserAcceleratorConfiguration() = default; - -base::optional_ref<const std::vector<ui::Accelerator>> -BrowserAcceleratorConfiguration::GetAcceleratorsForAction( - AcceleratorActionId action_id) { - // TODO(jimmyxgong): Implement stub. - return accelerators_; -} - -bool BrowserAcceleratorConfiguration::IsMutable() const { - return false; -} - -bool BrowserAcceleratorConfiguration::IsDeprecated( - const ui::Accelerator& accelerator) const { - // TODO(longbowei): Implement stub. - return false; -} - -AcceleratorConfigResult BrowserAcceleratorConfiguration::AddUserAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& accelerator) { - // TODO(jimmyxgong): Implement stub. - return AcceleratorConfigResult::kSuccess; -} - -AcceleratorConfigResult BrowserAcceleratorConfiguration::RemoveAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& accelerator) { - // TODO(jimmyxgong): Implement stub. - return AcceleratorConfigResult::kSuccess; -} - -AcceleratorConfigResult BrowserAcceleratorConfiguration::ReplaceAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& old_acc, - const ui::Accelerator& new_acc) { - // TODO(jimmyxgong): Implement stub. - return AcceleratorConfigResult::kSuccess; -} - -AcceleratorConfigResult BrowserAcceleratorConfiguration::RestoreDefault( - AcceleratorActionId action_id) { - // TODO(jimmyxgong): Implement stub. - return AcceleratorConfigResult::kSuccess; -} - -AcceleratorConfigResult BrowserAcceleratorConfiguration::RestoreAllDefaults() { - // TODO(jimmyxgong): Implement stub. - return AcceleratorConfigResult::kSuccess; -} - -} // namespace ash
diff --git a/chrome/browser/ash/browser_accelerator_configuration.h b/chrome/browser/ash/browser_accelerator_configuration.h deleted file mode 100644 index 8fb68ff..0000000 --- a/chrome/browser/ash/browser_accelerator_configuration.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ASH_BROWSER_ACCELERATOR_CONFIGURATION_H_ -#define CHROME_BROWSER_ASH_BROWSER_ACCELERATOR_CONFIGURATION_H_ - -#include "ash/ash_export.h" -#include "ash/public/cpp/accelerator_configuration.h" -#include "ash/public/mojom/accelerator_configuration.mojom.h" -#include "ash/public/mojom/accelerator_info.mojom.h" -#include "base/types/optional_ref.h" -#include "ui/base/accelerators/accelerator.h" - -#include <vector> - -namespace ash { - -// Implementor of AcceleratorConfiguration for LaCrOS/Chrome accelerators. -// The delegate exists here so that it is able to fetch browser accelerators -// from chrome/browser/ui/views and route it back to services in ash/. -// This class maintains a Mojo connection with a service in -// chrome/browser/ui/views in order to fetch LaCrOS specific shortcuts. -class ASH_EXPORT BrowserAcceleratorConfiguration - : public AcceleratorConfiguration { - public: - BrowserAcceleratorConfiguration(); - BrowserAcceleratorConfiguration(const BrowserAcceleratorConfiguration&) = - delete; - BrowserAcceleratorConfiguration& operator=( - const BrowserAcceleratorConfiguration&) = delete; - ~BrowserAcceleratorConfiguration() override; - - // AcceleratorConfiguration: - base::optional_ref<const std::vector<ui::Accelerator>> - GetAcceleratorsForAction(AcceleratorActionId action_id) override; - bool IsMutable() const override; - bool IsDeprecated(const ui::Accelerator& accelerator) const override; - mojom::AcceleratorConfigResult AddUserAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& accelerator) override; - mojom::AcceleratorConfigResult RemoveAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& accelerator) override; - mojom::AcceleratorConfigResult ReplaceAccelerator( - AcceleratorActionId action_id, - const ui::Accelerator& old_acc, - const ui::Accelerator& new_acc) override; - mojom::AcceleratorConfigResult RestoreDefault( - AcceleratorActionId action_id) override; - mojom::AcceleratorConfigResult RestoreAllDefaults() override; - - private: - std::vector<ui::Accelerator> accelerators_; - std::vector<mojom::AcceleratorLayoutInfoPtr> layout_infos_; -}; - -} // namespace ash - -#endif // CHROME_BROWSER_ASH_BROWSER_ACCELERATOR_CONFIGURATION_H_
diff --git a/chrome/browser/ash/browser_accelerator_configuration_unittest.cc b/chrome/browser/ash/browser_accelerator_configuration_unittest.cc deleted file mode 100644 index baeefa41..0000000 --- a/chrome/browser/ash/browser_accelerator_configuration_unittest.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ash/browser_accelerator_configuration.h" - -#include "ash/public/cpp/accelerator_configuration.h" -#include "ash/test/ash_test_base.h" - -namespace ash { -namespace { - -class BrowserAcceleratorConfigurationTest : public AshTestBase { - public: - BrowserAcceleratorConfigurationTest() = default; - BrowserAcceleratorConfigurationTest( - const BrowserAcceleratorConfigurationTest&) = delete; - BrowserAcceleratorConfigurationTest& operator=( - const BrowserAcceleratorConfigurationTest&) = delete; - ~BrowserAcceleratorConfigurationTest() override = default; - - void SetUp() override { - AshTestBase::SetUp(); - config_ = std::make_unique<BrowserAcceleratorConfiguration>(); - } - - protected: - std::unique_ptr<BrowserAcceleratorConfiguration> config_; -}; - -// TODO(jimmyxgong): Remove stub test after real implementation is available. -TEST_F(BrowserAcceleratorConfigurationTest, IsMutable) { - ASSERT_FALSE(config_->IsMutable()); -} - -} // namespace - -} // namespace ash
diff --git a/chrome/browser/ash/crosapi/search_controller_ash_unittest.cc b/chrome/browser/ash/crosapi/search_controller_ash_unittest.cc index 39cba16..c666689 100644 --- a/chrome/browser/ash/crosapi/search_controller_ash_unittest.cc +++ b/chrome/browser/ash/crosapi/search_controller_ash_unittest.cc
@@ -10,7 +10,11 @@ #include <utility> #include <vector> +#include "base/auto_reset.h" +#include "base/functional/callback.h" +#include "base/functional/callback_helpers.h" #include "base/memory/weak_ptr.h" +#include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" @@ -42,6 +46,13 @@ return receiver_.BindNewPipeAndPassRemote(); } + void RunUntilSearch() { + base::RunLoop loop; + base::AutoReset<base::RepeatingClosure> quit_loop(&search_callback_, + loop.QuitClosure()); + loop.Run(); + } + void ProduceResults( mojom::SearchStatus status, std::optional<std::vector<mojom::SearchResultPtr>> results) { @@ -56,8 +67,12 @@ publisher_.reset(); std::move(callback).Run(publisher_.BindNewEndpointAndPassReceiver()); + + search_callback_.Run(); } + base::RepeatingClosure search_callback_ = base::DoNothing(); + mojo::Receiver<mojom::SearchController> receiver_{this}; mojo::AssociatedRemote<mojom::SearchResultsPublisher> publisher_; std::u16string last_query_; @@ -79,14 +94,15 @@ TestMojomSearchController mojom_controller; controller = std::make_unique<SearchControllerAsh>(mojom_controller.BindToRemote()); - // Run until idle to ensure that the controller binds the remote... - environment.RunUntilIdle(); - // ...then destroy the receiver to disconnect it... } - // ...and ensure that the controller receives the disconnection. - environment.RunUntilIdle(); + { + base::RunLoop loop; + controller->AddDisconnectHandler( + SearchControllerAsh::DisconnectCallback(base::DoNothing()) + .Then(loop.QuitClosure())); + loop.Run(); + } controller->Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); EXPECT_FALSE(future.IsReady()); } @@ -97,12 +113,13 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); mojom_controller.ProduceResults(mojom::SearchStatus::kBackendUnavailable, std::nullopt); - environment.RunUntilIdle(); + // Run until `controller.OnSearchResultsReceived()` is called. + // TODO: b/326147929 - Use a `QuitClosure` for this. + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(future.IsReady()); } @@ -113,12 +130,14 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); mojom_controller.ProduceResults(mojom::SearchStatus::kBackendUnavailable, std::nullopt); - environment.RunUntilIdle(); + // Run until `controller.OnSearchResultsReceived()` is called. + // TODO: b/326147929 - Use a `QuitClosure` for this. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(future.IsReady()); } @@ -128,9 +147,8 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); mojom_controller.ProduceResults(mojom::SearchStatus::kDone, std::vector<mojom::SearchResultPtr>()); @@ -145,9 +163,8 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); std::vector<mojom::SearchResultPtr> results; { mojom::SearchResultPtr result = mojom::SearchResult::New(); @@ -182,9 +199,8 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); { std::vector<mojom::SearchResultPtr> results; @@ -224,9 +240,8 @@ TestMojomSearchController mojom_controller; SearchControllerAsh controller(mojom_controller.BindToRemote()); - environment.RunUntilIdle(); controller.Search(u"cat", future.GetRepeatingCallback()); - environment.RunUntilIdle(); + mojom_controller.RunUntilSearch(); { std::vector<mojom::SearchResultPtr> results; @@ -235,7 +250,9 @@ results.push_back(std::move(result)); mojom_controller.ProduceResults(mojom::SearchStatus::kInProgress, std::move(results)); - environment.RunUntilIdle(); + // Run until `controller.OnSearchResultsReceived()` is run. + // TODO: b/326147929 - Use a `QuitClosure` for this. + base::RunLoop().RunUntilIdle(); EXPECT_FALSE(future.IsReady()); } @@ -266,7 +283,7 @@ controller.AddDisconnectHandler(future.GetCallback()); mojom_controller.reset(); - environment.RunUntilIdle(); + ASSERT_TRUE(future.Wait()) << "Disconnect handler was never called"; ASSERT_FALSE(controller.IsConnected()); EXPECT_TRUE(future.IsReady()); @@ -286,7 +303,7 @@ controller.AddDisconnectHandler(future_1.GetCallback()); controller.AddDisconnectHandler(future_2.GetCallback()); mojom_controller.reset(); - environment.RunUntilIdle(); + ASSERT_TRUE(future_2.Wait()) << "Disconnect handler was never called"; ASSERT_FALSE(controller.IsConnected()); base::WeakPtr<SearchControllerAsh> weak_controller_1 = future_1.Take(); @@ -311,7 +328,7 @@ }))); controller.AddDisconnectHandler(future_2.GetCallback()); mojom_controller.reset(); - environment.RunUntilIdle(); + ASSERT_TRUE(future_2.Wait()) << "Disconnect handler was never called"; ASSERT_FALSE(controller.IsConnected()); // This also guarantees that the "first future called before second future" @@ -327,7 +344,13 @@ auto mojom_controller = std::make_unique<TestMojomSearchController>(); SearchControllerAsh controller(mojom_controller->BindToRemote()); mojom_controller.reset(); - environment.RunUntilIdle(); + { + base::RunLoop loop; + controller.AddDisconnectHandler( + SearchControllerAsh::DisconnectCallback(base::DoNothing()) + .Then(loop.QuitClosure())); + loop.Run(); + } ASSERT_FALSE(controller.IsConnected()); controller.AddDisconnectHandler(future.GetCallback()); @@ -363,9 +386,7 @@ })); controller->AddDisconnectHandler(future.GetCallback()); mojom_controller.reset(); - environment.RunUntilIdle(); - EXPECT_TRUE(future.IsReady()); base::WeakPtr<SearchControllerAsh> weak_controller = future.Take(); EXPECT_FALSE(weak_controller); }
diff --git a/chrome/browser/ash/customization/customization_wallpaper_util.cc b/chrome/browser/ash/customization/customization_wallpaper_util.cc index 2ffaff6..e03879c 100644 --- a/chrome/browser/ash/customization/customization_wallpaper_util.cc +++ b/chrome/browser/ash/customization/customization_wallpaper_util.cc
@@ -38,9 +38,8 @@ image, skia::ImageOperations::RESIZE_LANCZOS3, size); scoped_refptr<base::RefCountedBytes> image_data = new base::RefCountedBytes(); gfx::JPEGCodec::Encode(*resized_image.bitmap(), 90 /*quality=*/, - &image_data->data()); - return base::WriteFile( - file_path, base::make_span(image_data->front(), image_data->size())); + &image_data->as_vector()); + return base::WriteFile(file_path, *image_data); } // Returns true if both file paths exist.
diff --git a/chrome/browser/ash/data_migration/data_migration_factory.cc b/chrome/browser/ash/data_migration/data_migration_factory.cc index 0dd2e329..8c1afdd 100644 --- a/chrome/browser/ash/data_migration/data_migration_factory.cc +++ b/chrome/browser/ash/data_migration/data_migration_factory.cc
@@ -7,12 +7,12 @@ #include "base/functional/bind.h" #include "base/logging.h" #include "chrome/browser/ash/nearby/nearby_process_manager_factory.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chrome/browser/profiles/profile.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "chromeos/ash/components/browser_context_helper/browser_context_types.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/data_migration.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "chromeos/constants/chromeos_features.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ash/events/event_rewriter_unittest.cc b/chrome/browser/ash/events/event_rewriter_unittest.cc index 2441119..6b15867 100644 --- a/chrome/browser/ash/events/event_rewriter_unittest.cc +++ b/chrome/browser/ash/events/event_rewriter_unittest.cc
@@ -13,6 +13,7 @@ #include "ash/accessibility/sticky_keys/sticky_keys_overlay.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" +#include "ash/constants/ash_switches.h" #include "ash/public/cpp/input_device_settings_controller.h" #include "ash/public/cpp/test/mock_input_device_settings_controller.h" #include "ash/public/mojom/input_device_settings.mojom.h" @@ -462,6 +463,8 @@ const char* layout; ui::InputDeviceType type; bool has_custom_top_row; + bool has_assistant_key = false; + bool has_function_key = false; }; constexpr TestKeyboard kInternalChromeKeyboard = { "Internal Keyboard", @@ -475,6 +478,13 @@ ui::INPUT_DEVICE_INTERNAL, /*has_custom_top_row=*/true, }; +constexpr TestKeyboard kInternalChromeSplitModifierLayoutKeyboard = { + "Internal Custom Layout Keyboard", kKbdDefaultCustomTopRowLayout, + ui::INPUT_DEVICE_INTERNAL, + /*has_custom_top_row=*/true, + /*has_assistant_key=*/true, + /*has_function_key=*/true, +}; constexpr TestKeyboard kExternalChromeKeyboard = { "External Chrome Keyboard", kKbdTopRowLayout1Tag, @@ -519,9 +529,13 @@ kExternalGenericKeyboard, }; constexpr TestKeyboard kAllKeyboardVariants[] = { - kInternalChromeKeyboard, kInternalChromeCustomLayoutKeyboard, - kExternalChromeKeyboard, kExternalChromeCustomLayoutKeyboard, - kExternalGenericKeyboard, kExternalAppleKeyboard, + kInternalChromeKeyboard, + kInternalChromeCustomLayoutKeyboard, + kInternalChromeSplitModifierLayoutKeyboard, + kExternalChromeKeyboard, + kExternalChromeCustomLayoutKeyboard, + kExternalGenericKeyboard, + kExternalAppleKeyboard, }; // Wilco keyboard configs @@ -783,8 +797,9 @@ TestEventRewriterContinuation continuation; event_rewriter_ash_->RewriteMouseButtonEventForTesting( event, continuation.weak_ptr_factory_.GetWeakPtr()); - if (!continuation.rewritten_events.empty()) + if (!continuation.rewritten_events.empty()) { return ui::MouseEvent(*continuation.rewritten_events[0]->AsMouseEvent()); + } return ui::MouseEvent(event); } @@ -812,11 +827,13 @@ void SetUpKeyboard(const TestKeyboard& test_keyboard) { // Add a fake device to udev. - const ui::KeyboardDevice keyboard(kKeyboardDeviceId, test_keyboard.type, - test_keyboard.name, - /*phys=*/"", base::FilePath(kKbdSysPath), - /*vendor=*/-1, - /*product=*/-1, /*version=*/-1); + const ui::KeyboardDevice keyboard( + kKeyboardDeviceId, test_keyboard.type, test_keyboard.name, + /*phys=*/"", base::FilePath(kKbdSysPath), + /*vendor=*/-1, + /*product=*/-1, /*version=*/-1, + /*has_assistant_key=*/test_keyboard.has_assistant_key, + /*has_function_key=*/test_keyboard.has_function_key); // Old CrOS keyboards supply an integer/enum as a sysfs property to identify // their layout type. New keyboards provide the mapping of scan codes to @@ -2422,14 +2439,81 @@ for (auto& unknown : unknowns) { unknown.scan_code = scan_code; } + auto unknowns_with_function = KeyUnknown::Typed(ui::EF_FUNCTION_DOWN); + for (auto& unknown : unknowns_with_function) { + unknown.scan_code = scan_code; + } auto expected_events = typed(ui::EF_NONE); for (auto& event : expected_events) { event.scan_code = scan_code; } EXPECT_EQ(expected_events, RunRewriter(unknowns, ui::EF_COMMAND_DOWN)); + + // With fn down, nothing should change since this keyboard uses Search based + // rewriting. + EXPECT_EQ(unknowns_with_function, + RunRewriter(unknowns, ui::EF_FUNCTION_DOWN)); } } +TEST_P(EventRewriterTest, TestRewriteFunctionKeysCustomLayoutsWithFunction) { + scoped_feature_list_.InitAndEnableFeature(features::kModifierSplit); + auto reset = switches::SetIgnoreModifierSplitSecretKeyForTest(); + Preferences::RegisterProfilePrefs(prefs()->registry()); + + // On devices with custom layouts, scan codes that match the layout + // map get mapped to F-Keys based only on the scan code. The search + // key also gets treated as unpressed in the remapped event. + SetUpKeyboard({.name = "Internal Custom Layout Keyboard", + .layout = "a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af", + .type = ui::INPUT_DEVICE_INTERNAL, + .has_custom_top_row = true, + .has_assistant_key = true, + .has_function_key = true}); + + struct TestCase { + std::vector<TestKeyEvent> (*pressed)(ui::EventFlags); + uint32_t scan_code; + }; + // Action -> F1..F15 + for (const auto& [typed, scan_code] : + std::initializer_list<TestCase>{{KeyF1::Typed, 0xa1}, + {KeyF2::Typed, 0xa2}, + {KeyF3::Typed, 0xa3}, + {KeyF4::Typed, 0xa4}, + {KeyF5::Typed, 0xa5}, + {KeyF6::Typed, 0xa6}, + {KeyF7::Typed, 0xa7}, + {KeyF8::Typed, 0xa8}, + {KeyF9::Typed, 0xa9}, + {KeyF10::Typed, 0xaa}, + {KeyF11::Typed, 0xab}, + {KeyF12::Typed, 0xac}, + {KeyF13::Typed, 0xad}, + {KeyF14::Typed, 0xae}, + {KeyF15::Typed, 0xaf}}) { + auto unknowns = KeyUnknown::Typed(); + for (auto& unknown : unknowns) { + unknown.scan_code = scan_code; + } + auto unknowns_with_search = KeyUnknown::Typed(ui::EF_COMMAND_DOWN); + for (auto& unknown : unknowns_with_search) { + unknown.scan_code = scan_code; + } + auto expected_events = typed(ui::EF_NONE); + for (auto& event : expected_events) { + event.scan_code = scan_code; + } + // Do not rewrite when search key is down since the keyboard should use the + // fn key. + EXPECT_EQ(unknowns_with_search, RunRewriter(unknowns, ui::EF_COMMAND_DOWN)); + + // Rewrite correctly with the fn key down. + EXPECT_EQ(expected_events, RunRewriter(unknowns, ui::EF_FUNCTION_DOWN)); + } + scoped_feature_list_.Reset(); +} + TEST_P(EventRewriterTest, TestRewriteFunctionKeysLayout2) { Preferences::RegisterProfilePrefs(prefs()->registry()); SetUpKeyboard({.name = "Internal Keyboard",
diff --git a/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc b/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc index ad97c426..2a6e2320 100644 --- a/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc +++ b/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc
@@ -50,12 +50,15 @@ } void Capture(std::string* result, scoped_refptr<base::RefCountedMemory> data) { - *result = std::string(data->front_as<char>(), data->size()); + *result = std::string(base::as_string_view(*data)); } void CaptureUTF16(std::string* result, scoped_refptr<base::RefCountedMemory> data) { - base::UTF16ToUTF8(data->front_as<char16_t>(), data->size() / 2, result); + base::span<const uint8_t> bytes = *data; + std::u16string str(bytes.size() / 2u, u'\0'); + base::as_writable_byte_span(str).copy_from(bytes); + *result = base::UTF16ToUTF8(str); } } // namespace
diff --git a/chrome/browser/ash/input_method/editor_switch.cc b/chrome/browser/ash/input_method/editor_switch.cc index 9f3d139..0feba68a 100644 --- a/chrome/browser/ash/input_method/editor_switch.cc +++ b/chrome/browser/ash/input_method/editor_switch.cc
@@ -434,10 +434,6 @@ MaybeNotifyEditorModeChanged(prev_mode); } -void EditorSwitch::SetProfile(Profile* profile) { - profile_ = profile; -} - void EditorSwitch::MaybeNotifyEditorModeChanged(const EditorMode& prev_mode) { EditorMode new_mode = GetEditorMode(); if (prev_mode != new_mode) {
diff --git a/chrome/browser/ash/input_method/editor_switch.h b/chrome/browser/ash/input_method/editor_switch.h index d964792..f920202 100644 --- a/chrome/browser/ash/input_method/editor_switch.h +++ b/chrome/browser/ash/input_method/editor_switch.h
@@ -47,8 +47,6 @@ void OnTextSelectionLengthChanged(size_t new_length); - void SetProfile(Profile* profile); - EditorMode GetEditorMode() const; EditorOpportunityMode GetEditorOpportunityMode() const;
diff --git a/chrome/browser/ash/login/OWNERS b/chrome/browser/ash/login/OWNERS index b31e5124..96f4bb7 100644 --- a/chrome/browser/ash/login/OWNERS +++ b/chrome/browser/ash/login/OWNERS
@@ -12,3 +12,6 @@ per-file *challenge_response*=fabiansommer@chromium.org per-file *security_token*=emaxx@chromium.org per-file *security_token*=fabiansommer@chromium.org + +per-file *quickstart_controller*=bhartmire@google.com +per-file *quickstart_controller*=hansenmichael@google.com
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.cc index a415326..4395e54a 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.cc
@@ -106,6 +106,7 @@ scoped_refptr<device::BluetoothAdapter> adapter) { DCHECK(adapter && adapter->IsPresent() && adapter->IsPowered()); adapter_ = adapter; + quick_start_metrics_ = std::make_unique<QuickStartMetrics>(); } FastPairAdvertiser::~FastPairAdvertiser() { @@ -123,7 +124,6 @@ const AdvertisingId& advertising_id) { DCHECK(adapter_->IsPresent() && adapter_->IsPowered()); DCHECK(!advertisement_); - quick_start_metrics_.RecordFastPairAdvertisementStarted(); RegisterAdvertisement(std::move(callback), std::move(error_callback), advertising_id); } @@ -174,6 +174,9 @@ void FastPairAdvertiser::OnRegisterAdvertisement( base::OnceClosure callback, scoped_refptr<device::BluetoothAdvertisement> advertisement) { + quick_start_metrics_->RecordFastPairAdvertisementStarted( + /*succeeded=*/true, + /*error_code=*/std::nullopt); advertisement_ = advertisement; advertisement_->AddObserver(this); std::move(callback).Run(); @@ -183,11 +186,9 @@ base::OnceClosure error_callback, device::BluetoothAdvertisement::ErrorCode error_code) { LOG(ERROR) << __func__ << " failed with error code = " << error_code; - QuickStartMetrics::FastPairAdvertisingErrorCode uma_error_code_enum = - MapBluetoothAdvertisementErrorCode(error_code); - quick_start_metrics_.RecordFastPairAdvertisementEnded( + quick_start_metrics_->RecordFastPairAdvertisementStarted( /*succeeded=*/false, - /*error_code=*/uma_error_code_enum); + /*error_code=*/MapBluetoothAdvertisementErrorCode(error_code)); std::move(error_callback).Run(); // |this| might be destroyed here, do not access local fields. } @@ -204,7 +205,7 @@ void FastPairAdvertiser::OnUnregisterAdvertisement() { advertisement_.reset(); - quick_start_metrics_.RecordFastPairAdvertisementEnded( + quick_start_metrics_->RecordFastPairAdvertisementEnded( /*succeeded=*/true, /*error_code=*/std::nullopt); @@ -216,7 +217,9 @@ device::BluetoothAdvertisement::ErrorCode error_code) { LOG(WARNING) << __func__ << " failed with error code = " << error_code; advertisement_.reset(); - + quick_start_metrics_->RecordFastPairAdvertisementEnded( + /*succeeded=*/false, + /*error_code=*/MapBluetoothAdvertisementErrorCode(error_code)); std::move(stop_callback_).Run(); // |this| might be destroyed here, do not access local fields. }
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.h index 89615be7..489e299 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.h +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser.h
@@ -85,7 +85,7 @@ scoped_refptr<device::BluetoothAdapter> adapter_; scoped_refptr<device::BluetoothAdvertisement> advertisement_; base::OnceClosure stop_callback_; - QuickStartMetrics quick_start_metrics_; + std::unique_ptr<QuickStartMetrics> quick_start_metrics_; base::WeakPtrFactory<FastPairAdvertiser> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc index 8b080b8..3057fae 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/fast_pair_advertiser_unittest.cc
@@ -196,32 +196,48 @@ fast_pair_advertiser_ = std::make_unique<FastPairAdvertiser>(mock_adapter_); } - void TestExpectedMetrics( + void TestExpectedStartMetrics( bool should_succeed, std::optional<device::BluetoothAdvertisement::ErrorCode> error_code) { - expected_total_count_++; - histograms_.ExpectTotalCount( - "QuickStart.FastPairAdvertisementEnded.Duration", - expected_total_count_); - histograms_.ExpectTotalCount("QuickStart.FastPairAdvertisementStarted", - expected_total_count_); - if (should_succeed) { - expected_success_count_++; + expected_start_success_count_++; histograms_.ExpectBucketCount( - "QuickStart.FastPairAdvertisementEnded.Succeeded", true, - expected_success_count_); + "QuickStart.FastPairAdvertisementStarted.Succeeded", true, + expected_start_success_count_); return; } - expected_failure_count_++; - expected_error_bucket_count_++; + expected_start_failure_count_++; + expected_start_error_bucket_count_++; + histograms_.ExpectBucketCount( + "QuickStart.FastPairAdvertisementStarted.Succeeded", false, + expected_start_failure_count_); + histograms_.ExpectBucketCount( + "QuickStart.FastPairAdvertisementStarted.ErrorCode", error_code.value(), + expected_start_error_bucket_count_); + } + + void TestExpectedStopMetrics( + bool should_succeed, + std::optional<device::BluetoothAdvertisement::ErrorCode> error_code) { + if (should_succeed) { + expected_end_success_count_++; + histograms_.ExpectBucketCount( + "QuickStart.FastPairAdvertisementEnded.Succeeded", true, + expected_end_success_count_); + histograms_.ExpectTotalCount( + "QuickStart.FastPairAdvertisementEnded.Duration", + expected_end_success_count_); + return; + } + + expected_end_failure_count_++; histograms_.ExpectBucketCount( "QuickStart.FastPairAdvertisementEnded.Succeeded", false, - expected_failure_count_); + expected_end_failure_count_); histograms_.ExpectBucketCount( "QuickStart.FastPairAdvertisementEnded.ErrorCode", error_code.value(), - expected_error_bucket_count_); + expected_end_failure_count_); } void OnAdapterRegisterAdvertisement(RegisterAdvertisementArgs* args) { @@ -263,7 +279,9 @@ return fast_pair_advertiser_->GenerateManufacturerMetadata(advertising_id); } - void ResetExpectedErrorBucketCount() { expected_error_bucket_count_ = 0; } + void ResetExpectedErrorBucketCount() { + expected_start_error_bucket_count_ = 0; + } void SetAdvertisementErrorsForMetricsTesting( device::BluetoothAdvertisement::ErrorCode error_code) { @@ -272,7 +290,7 @@ EXPECT_FALSE(called_on_start_advertising()); EXPECT_TRUE(called_on_start_advertising_error()); - TestExpectedMetrics(/*should_succeed=*/false, error_code); + TestExpectedStartMetrics(/*should_succeed=*/false, error_code); } scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> mock_adapter_; @@ -282,10 +300,11 @@ bool called_on_start_advertising_ = false; bool called_on_start_advertising_error_ = false; bool called_on_stop_advertising_ = false; - base::HistogramBase::Count expected_success_count_ = 0; - base::HistogramBase::Count expected_failure_count_ = 0; - base::HistogramBase::Count expected_error_bucket_count_ = 0; - base::HistogramBase::Count expected_total_count_ = 0; + base::HistogramBase::Count expected_start_success_count_ = 0; + base::HistogramBase::Count expected_start_failure_count_ = 0; + base::HistogramBase::Count expected_start_error_bucket_count_ = 0; + base::HistogramBase::Count expected_end_success_count_ = 0; + base::HistogramBase::Count expected_end_failure_count_ = 0; }; class FastPairAdvertiserModelIdsTest @@ -307,6 +326,8 @@ EXPECT_FALSE(called_on_start_advertising_error()); EXPECT_FALSE(called_on_stop_advertising()); EXPECT_TRUE(fake_advertisement->HasObserver(fast_pair_advertiser_.get())); + TestExpectedStartMetrics(/*should_succeed=*/true, + /*error_code=*/std::nullopt); } TEST_F(FastPairAdvertiserTest, TestStartAdvertising_Error) { @@ -318,9 +339,9 @@ EXPECT_FALSE(called_on_start_advertising()); EXPECT_TRUE(called_on_start_advertising_error()); EXPECT_FALSE(called_on_stop_advertising()); - TestExpectedMetrics(/*should_succeed=*/false, - /*error_code=*/device::BluetoothAdvertisement::ErrorCode:: - INVALID_ADVERTISEMENT_ERROR_CODE); + TestExpectedStartMetrics(/*should_succeed=*/false, + /*error_code=*/device::BluetoothAdvertisement:: + ErrorCode::INVALID_ADVERTISEMENT_ERROR_CODE); } TEST_F(FastPairAdvertiserTest, TestStopAdvertising_Success) { @@ -336,7 +357,7 @@ EXPECT_TRUE(called_on_start_advertising()); EXPECT_FALSE(called_on_start_advertising_error()); EXPECT_TRUE(called_on_stop_advertising()); - TestExpectedMetrics(/*should_succeed=*/true, /*error_code=*/std::nullopt); + TestExpectedStopMetrics(/*should_succeed=*/true, /*error_code=*/std::nullopt); } TEST_F(FastPairAdvertiserTest, TestStopAdvertising_Error) { @@ -352,6 +373,9 @@ EXPECT_TRUE(called_on_start_advertising()); EXPECT_FALSE(called_on_start_advertising_error()); EXPECT_TRUE(called_on_stop_advertising()); + TestExpectedStopMetrics(/*should_succeed=*/false, + /*error_code=*/device::BluetoothAdvertisement:: + ErrorCode::INVALID_ADVERTISEMENT_ERROR_CODE); } TEST_F(FastPairAdvertiserTest, TestAdvertisementReleased) { @@ -424,15 +448,9 @@ INVALID_ADVERTISEMENT_ERROR_CODE); EXPECT_FALSE(fast_pair_advertiser_); - expected_failure_count_++; - histograms_.ExpectBucketCount( - "QuickStart.FastPairAdvertisementEnded.Succeeded", false, - expected_failure_count_); - histograms_.ExpectBucketCount( - "QuickStart.FastPairAdvertisementEnded.ErrorCode", - device::BluetoothAdvertisement::ErrorCode:: - INVALID_ADVERTISEMENT_ERROR_CODE, - expected_failure_count_); + TestExpectedStartMetrics(/*should_succeed=*/false, + /*error_code=*/device::BluetoothAdvertisement:: + ErrorCode::INVALID_ADVERTISEMENT_ERROR_CODE); } TEST_F(FastPairAdvertiserTest, TestStopAdvertisingSuccess_DeleteInCallback) { @@ -448,6 +466,8 @@ EXPECT_FALSE(fake_advertisement->called_unregister_error_callback()); EXPECT_TRUE(called_on_start_advertising()); EXPECT_FALSE(called_on_start_advertising_error()); + TestExpectedStopMetrics(/*should_succeed=*/true, + /*error_code=*/std::nullopt); } TEST_F(FastPairAdvertiserTest, TestStopAdvertisingError_DeleteInCallback) { @@ -463,6 +483,9 @@ EXPECT_TRUE(fake_advertisement->called_unregister_error_callback()); EXPECT_TRUE(called_on_start_advertising()); EXPECT_FALSE(called_on_start_advertising_error()); + TestExpectedStopMetrics(/*should_succeed=*/false, + /*error_code=*/device::BluetoothAdvertisement:: + ErrorCode::INVALID_ADVERTISEMENT_ERROR_CODE); } TEST_P(FastPairAdvertiserModelIdsTest, ModelIds) {
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc index 9f142a27..9b16d656 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.cc
@@ -103,6 +103,60 @@ return std::vector<uint8_t>(output.begin(), output.end()); } +std::optional<QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode> +MapConnectionsStatusToErrorCode( + NearbyConnectionsManager::ConnectionsStatus status) { + switch (status) { + case NearbyConnectionsManager::ConnectionsStatus::kSuccess: + return std::nullopt; + case NearbyConnectionsManager::ConnectionsStatus::kError: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode::kError; + case NearbyConnectionsManager::ConnectionsStatus::kOutOfOrderApiCall: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode:: + kOutOfOrderApiCall; + case NearbyConnectionsManager::ConnectionsStatus:: + kAlreadyHaveActiveStrategy: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode:: + kAlreadyHaveActiveStrategy; + case NearbyConnectionsManager::ConnectionsStatus::kAlreadyAdvertising: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode:: + kAlreadyAdvertising; + case NearbyConnectionsManager::ConnectionsStatus::kBluetoothError: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode:: + kBluetoothError; + case NearbyConnectionsManager::ConnectionsStatus::kBleError: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode:: + kBleError; + case NearbyConnectionsManager::ConnectionsStatus::kTimeout: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode::kTimeout; + case NearbyConnectionsManager::ConnectionsStatus::kUnknown: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode::kUnknown; + case NearbyConnectionsManager::ConnectionsStatus::kAlreadyDiscovering: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kEndpointIOError: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kEndpointUnknown: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kConnectionRejected: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus:: + kAlreadyConnectedToEndpoint: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kNotConnectedToEndpoint: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kWifiLanError: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kPayloadUnknown: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kAlreadyListening: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kReset: + [[fallthrough]]; + case NearbyConnectionsManager::ConnectionsStatus::kNextValue: + return QuickStartMetrics::NearbyConnectionsAdvertisingErrorCode::kOther; + } +} + } // namespace void TargetDeviceConnectionBrokerImpl::BluetoothAdapterFactoryWrapper:: @@ -134,6 +188,7 @@ quick_start_connectivity_service_(quick_start_connectivity_service), connection_factory_(std::move(connection_factory)) { GetBluetoothAdapter(); + quick_start_metrics_ = std::make_unique<QuickStartMetrics>(); } TargetDeviceConnectionBrokerImpl::~TargetDeviceConnectionBrokerImpl() {} @@ -371,6 +426,9 @@ weak_ptr_factory_.GetWeakPtr())); } + quick_start_metrics_->RecordNearbyConnectionsAdvertisementStarted( + success, MapConnectionsStatusToErrorCode(status)); + std::move(callback).Run(success); } @@ -379,9 +437,16 @@ NearbyConnectionsManager::ConnectionsStatus status) { QS_LOG(INFO) << "Nearby Connections Advertising stopped with status " << status; - if (status != NearbyConnectionsManager::ConnectionsStatus::kSuccess) { + bool success = + status == NearbyConnectionsManager::ConnectionsStatus::kSuccess; + + if (!success) { QS_LOG(WARNING) << "Failed to stop Nearby Connections advertising"; } + + quick_start_metrics_->RecordNearbyConnectionsAdvertisementEnded( + success, MapConnectionsStatusToErrorCode(status)); + std::move(callback).Run(); }
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.h b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.h index e5a2508..2f46f35 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.h +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.h
@@ -120,6 +120,7 @@ raw_ptr<QuickStartConnectivityService> quick_start_connectivity_service_; std::unique_ptr<Connection::Factory> connection_factory_; std::unique_ptr<Connection> connection_; + std::unique_ptr<QuickStartMetrics> quick_start_metrics_; base::OneShotTimer nearby_connections_advertisement_after_update_timeout_timer_;
diff --git a/chrome/browser/ash/login/screens/user_selection_screen.cc b/chrome/browser/ash/login/screens/user_selection_screen.cc index 51e9ed0f..ea77c79 100644 --- a/chrome/browser/ash/login/screens/user_selection_screen.cc +++ b/chrome/browser/ash/login/screens/user_selection_screen.cc
@@ -857,7 +857,7 @@ } else { std::tie(user_info.is_multi_user_sign_in_allowed, user_info.multi_user_sign_in_policy) = - GetMultiUserSignInPolicy(user); + ash::GetMultiUserSignInPolicy(user); } // Fill public session data.
diff --git a/chrome/browser/ash/login/users/avatar/user_image_loader.cc b/chrome/browser/ash/login/users/avatar/user_image_loader.cc index 997c3d9..1dbe9acd 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_loader.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_loader.cc
@@ -297,7 +297,7 @@ auto encoded = base::MakeRefCounted<base::RefCountedBytes>(); if (!gfx::PNGCodec::EncodeBGRASkBitmap( bitmap, /*discard_transparency=*/false, - &encoded->data())) { + &encoded->as_vector())) { return std::make_unique<user_manager::UserImage>(); }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_loader_unittest.cc b/chrome/browser/ash/login/users/avatar/user_image_loader_unittest.cc index f3ad64f..a6822fe 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_loader_unittest.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_loader_unittest.cc
@@ -60,8 +60,9 @@ task_environment_.GetMainThreadTaskRunner(), image_path, base::BindLambdaForTesting( [&](std::unique_ptr<user_manager::UserImage> user_image) { - auto data = user_image->image_bytes()->data(); - EXPECT_EQ(original_contents, std::string(data.begin(), data.end())); + EXPECT_EQ( + original_contents, + std::string(base::as_string_view(*user_image->image_bytes()))); EXPECT_EQ(user_manager::UserImage::FORMAT_WEBP, user_image->image_format()); EXPECT_EQ(16, user_image->image().width());
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc index 3d0b38e..3731946 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -147,21 +147,6 @@ } } -bool GetUserLockAttributes(const user_manager::User* user, - MultiUserSignInPolicy* policy) { - Profile* const profile = ProfileHelper::Get()->GetProfileByUser(user); - if (!profile) { - return false; - } - PrefService* const prefs = profile->GetPrefs(); - if (policy) { - *policy = ParseMultiUserSignInPolicyPref( - prefs->GetString(prefs::kMultiProfileUserBehaviorPref)) - .value_or(MultiUserSignInPolicy::kUnrestricted); - } - return true; -} - policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() { return g_browser_process->platform_part() ->browser_policy_connector_ash() @@ -419,7 +404,7 @@ } // No user is allowed if the primary user policy forbids it. - if (multi_user_sign_in_policy_controller_.GetPrimaryUserPolicy() == + if (user_manager::GetMultiUserSignInPolicy(GetPrimaryUser()) == MultiUserSignInPolicy::kNotAllowed) { return {}; } @@ -445,9 +430,10 @@ return user_manager::UserList(); } - MultiUserSignInPolicy primary_policy; auto* primary_user = GetPrimaryUser(); - if (!GetUserLockAttributes(primary_user, &primary_policy)) { + std::optional<MultiUserSignInPolicy> primary_policy = + user_manager::GetMultiUserSignInPolicy(primary_user); + if (!primary_policy.has_value()) { // Locking is not allowed until the primary user profile is created. return user_manager::UserList(); } @@ -464,8 +450,9 @@ } else { // Fill list of potential unlock users based on multi-user policy state. for (user_manager::User* user : logged_in_users) { - MultiUserSignInPolicy policy; - if (!GetUserLockAttributes(user, &policy)) { + std::optional<MultiUserSignInPolicy> policy = + user_manager::GetMultiUserSignInPolicy(user); + if (!policy.has_value()) { continue; } if (policy == MultiUserSignInPolicy::kUnrestricted && user->CanLock()) {
diff --git a/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc index 88c2d74..5c92711 100644 --- a/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc +++ b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc
@@ -224,7 +224,8 @@ SetCachedBehavior(0, kTestCases[i]); EXPECT_TRUE( controller()->IsUserAllowedInSession(test_users_[0].GetUserEmail())); - EXPECT_EQ(std::nullopt, controller()->GetPrimaryUserPolicy()); + EXPECT_EQ(std::nullopt, + GetMultiUserSignInPolicy(fake_user_manager_->GetPrimaryUser())); } } @@ -293,8 +294,9 @@ SCOPED_TRACE(i); SetPrefBehavior(0, kBehaviorTestCases[i].primary); SetCachedBehavior(1, kBehaviorTestCases[i].secondary); + EXPECT_EQ(kBehaviorTestCases[i].primary, - controller()->GetPrimaryUserPolicy()); + GetMultiUserSignInPolicy(fake_user_manager_->GetPrimaryUser())); EXPECT_EQ( kBehaviorTestCases[i].expected_secondary_allowed, controller()->IsUserAllowedInSession(test_users_[1].GetUserEmail()));
diff --git a/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.cc b/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.cc index 8369df84..988442b 100644 --- a/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.cc +++ b/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.cc
@@ -75,6 +75,27 @@ success); } +void RecordCredentialStorageRetrieveLocalPublicCredentialsResult(bool success) { + base::UmaHistogramBoolean( + "Nearby.Presence.Credentials.Storage.RetrieveLocalPublicCredentials." + "Result", + success); +} + +void RecordCredentialStorageRetrieveRemotePublicCredentialsResult( + bool success) { + base::UmaHistogramBoolean( + "Nearby.Presence.Credentials.Storage.RetrieveRemotePublicCredentials." + "Result", + success); +} + +void RecordCredentialStorageRetrievePrivateCredentialsResult(bool success) { + base::UmaHistogramBoolean( + "Nearby.Presence.Credentials.Storage.RetrievePrivateCredentials.Result", + success); +} + void RecordCredentialStorageRetrieveLocalPublicCredentialsDuration( base::TimeDelta duration) { base::UmaHistogramMicrosecondsTimes( @@ -98,4 +119,28 @@ duration); } +void RecordNumberOfLocalSharedCredentials(int num_credentials) { + base::UmaHistogramCounts100( + "Nearby.Presence.Credentials.Storage.LocalSharedCredentials.Count", + num_credentials); +} + +void RecordNumberOfRemoteSharedCredentials(int num_credentials) { + base::UmaHistogramCounts100( + "Nearby.Presence.Credentials.Storage.RemoteSharedCredentials.Count", + num_credentials); +} + +void RecordSizeOfLocalSharedCredentials(size_t credentials_size_in_bytes) { + base::UmaHistogramMemoryKB( + "Nearby.Presence.Credentials.Storage.LocalSharedCredentials.Size", + credentials_size_in_bytes); +} + +void RecordSizeOfRemoteSharedCredentials(size_t credentials_size_in_bytes) { + base::UmaHistogramMemoryKB( + "Nearby.Presence.Credentials.Storage.RemoteSharedCredentials.Size", + credentials_size_in_bytes); +} + } // namespace ash::nearby::presence::metrics
diff --git a/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.h b/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.h index 753c31e..a7c5cbd 100644 --- a/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.h +++ b/chrome/browser/ash/nearby/presence/credential_storage/metrics/credential_storage_metrics.h
@@ -26,6 +26,10 @@ void RecordCredentialStorageSaveRemotePublicCredentialsResult(bool success); void RecordCredentialStorageSavePrivateCredentialsResult(bool success); +void RecordCredentialStorageRetrieveLocalPublicCredentialsResult(bool success); +void RecordCredentialStorageRetrieveRemotePublicCredentialsResult(bool success); +void RecordCredentialStorageRetrievePrivateCredentialsResult(bool success); + void RecordCredentialStorageRetrieveLocalPublicCredentialsDuration( base::TimeDelta duration); void RecordCredentialStorageRetrieveRemotePublicCredentialsDuration( @@ -33,6 +37,16 @@ void RecordCredentialStorageRetrievePrivateCredentialsDuration( base::TimeDelta duration); +// Note: RecordNumberOfLocalCredentials is intentionally not captured: +// the number is constant across all devices (6). +void RecordNumberOfLocalSharedCredentials(int number_of_credentials); +void RecordNumberOfRemoteSharedCredentials(int number_of_credentials); + +// Note: RecordSizeOfLocalCredentials is intentionally not captured: +// the size is constant across all devices. +void RecordSizeOfLocalSharedCredentials(size_t credentials_size_in_bytes); +void RecordSizeOfRemoteSharedCredentials(size_t credentials_size_in_bytes); + } // namespace ash::nearby::presence::metrics #endif // CHROME_BROWSER_ASH_NEARBY_PRESENCE_CREDENTIAL_STORAGE_METRICS_CREDENTIAL_STORAGE_METRICS_H_
diff --git a/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.cc b/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.cc index ceba002..61fe261 100644 --- a/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.cc +++ b/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.cc
@@ -235,19 +235,19 @@ std::unique_ptr<std::vector<::nearby::internal::LocalCredential>> entries) { CHECK(callback); - if (!success) { - // TODO(b/287334363): Emit a failure metric. + metrics::RecordCredentialStorageRetrievePrivateCredentialsResult(success); + if (success) { + base::TimeDelta retrieval_duration = + base::TimeTicks::Now() - retrieval_start_time; + metrics::RecordCredentialStorageRetrievePrivateCredentialsDuration( + retrieval_duration); + } else { LOG(ERROR) << __func__ << ": failed to retrieve private credentials"; std::move(callback).Run(mojo_base::mojom::AbslStatusCode::kAborted, std::nullopt); return; } - base::TimeDelta retrieval_duration = - base::TimeTicks::Now() - retrieval_start_time; - metrics::RecordCredentialStorageRetrievePrivateCredentialsDuration( - retrieval_duration); - CHECK(entries); std::vector<ash::nearby::presence::mojom::LocalCredentialPtr> @@ -270,27 +270,36 @@ entries) { CHECK(callback); - if (!success) { - // TODO(b/287334363): Emit a failure metric. + switch (public_credential_type) { + case (mojom::PublicCredentialType::kLocalPublicCredential): + metrics::RecordCredentialStorageRetrieveLocalPublicCredentialsResult( + success); + break; + case (mojom::PublicCredentialType::kRemotePublicCredential): + metrics::RecordCredentialStorageRetrieveRemotePublicCredentialsResult( + success); + break; + } + if (success) { + base::TimeDelta retrieval_duration = + base::TimeTicks::Now() - retrieval_start_time; + switch (public_credential_type) { + case (mojom::PublicCredentialType::kLocalPublicCredential): + metrics::RecordCredentialStorageRetrieveLocalPublicCredentialsDuration( + retrieval_duration); + break; + case (mojom::PublicCredentialType::kRemotePublicCredential): + metrics::RecordCredentialStorageRetrieveRemotePublicCredentialsDuration( + retrieval_duration); + break; + } + } else { LOG(ERROR) << __func__ << ": failed to retrieve public credentials"; std::move(callback).Run(mojo_base::mojom::AbslStatusCode::kAborted, std::nullopt); return; } - base::TimeDelta retrieval_duration = - base::TimeTicks::Now() - retrieval_start_time; - switch (public_credential_type) { - case (mojom::PublicCredentialType::kLocalPublicCredential): - metrics::RecordCredentialStorageRetrieveLocalPublicCredentialsDuration( - retrieval_duration); - break; - case (mojom::PublicCredentialType::kRemotePublicCredential): - metrics::RecordCredentialStorageRetrieveRemotePublicCredentialsDuration( - retrieval_duration); - break; - } - CHECK(entries); std::vector<ash::nearby::presence::mojom::SharedCredentialPtr> @@ -477,6 +486,60 @@ receiver_.Bind(std::move(pending_receiver_)); std::move(on_fully_initialized).Run(/*success=*/true); + + RecordCredentialsCountAndSize(); +} + +void NearbyPresenceCredentialStorage::RecordCredentialsCountAndSize() { + local_public_db_->LoadEntries( + base::BindOnce(&NearbyPresenceCredentialStorage:: + RecordLocalSharedCredentialsCountAndSize, + weak_ptr_factory_.GetWeakPtr())); +} + +void NearbyPresenceCredentialStorage::RecordLocalSharedCredentialsCountAndSize( + bool success, + std::unique_ptr<std::vector<::nearby::internal::SharedCredential>> + entries) { + if (!success) { + LOG(ERROR) + << __func__ + << ": failed to load entries for local shared credential database."; + return; + } + + metrics::RecordNumberOfLocalSharedCredentials(entries->size()); + + size_t size_of_credentials_in_bytes = 0; + for (const auto& entry : *entries) { + size_of_credentials_in_bytes += entry.ByteSizeLong(); + } + metrics::RecordSizeOfLocalSharedCredentials(size_of_credentials_in_bytes); + + remote_public_db_->LoadEntries( + base::BindOnce(&NearbyPresenceCredentialStorage:: + RecordRemoteSharedCredentialsCountAndSize, + weak_ptr_factory_.GetWeakPtr())); +} + +void NearbyPresenceCredentialStorage::RecordRemoteSharedCredentialsCountAndSize( + bool success, + std::unique_ptr<std::vector<::nearby::internal::SharedCredential>> + entries) { + if (!success) { + LOG(ERROR) + << __func__ + << ": failed to load entries for remote shared credential database."; + return; + } + + metrics::RecordNumberOfRemoteSharedCredentials(entries->size()); + + size_t size_of_credentials_in_bytes = 0; + for (const auto& entry : *entries) { + size_of_credentials_in_bytes += entry.ByteSizeLong(); + } + metrics::RecordSizeOfRemoteSharedCredentials(size_of_credentials_in_bytes); } } // namespace ash::nearby::presence
diff --git a/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.h b/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.h index 9eccde7..52d6116e 100644 --- a/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.h +++ b/chrome/browser/ash/nearby/presence/credential_storage/nearby_presence_credential_storage.h
@@ -125,6 +125,16 @@ base::TimeTicks initialization_start_time, leveldb_proto::Enums::InitStatus remote_public_db_initialization_status); + void RecordCredentialsCountAndSize(); + void RecordLocalSharedCredentialsCountAndSize( + bool success, + std::unique_ptr<std::vector<::nearby::internal::SharedCredential>> + entries); + void RecordRemoteSharedCredentialsCountAndSize( + bool success, + std::unique_ptr<std::vector<::nearby::internal::SharedCredential>> + entries); + std::unique_ptr< leveldb_proto::ProtoDatabase<::nearby::internal::LocalCredential>> private_db_;
diff --git a/chrome/browser/ash/nearby/quick_start_connectivity_service_impl.cc b/chrome/browser/ash/nearby/quick_start_connectivity_service_impl.cc index 19ad25f..7940dff 100644 --- a/chrome/browser/ash/nearby/quick_start_connectivity_service_impl.cc +++ b/chrome/browser/ash/nearby/quick_start_connectivity_service_impl.cc
@@ -6,8 +6,8 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "chromeos/ash/services/nearby/public/cpp/nearby_process_manager.h" #include "chromeos/ash/services/nearby/public/mojom/quick_start_decoder.mojom.h" #include "mojo/public/cpp/bindings/shared_remote.h"
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc index b603cbe0..455c7ca 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -297,9 +297,8 @@ } scoped_refptr<base::RefCountedMemory> png_data = GetScreenshotData(); - if (report->include_screenshot && png_data && png_data.get()) { - feedback_data->set_image( - std::string(png_data->front_as<char>(), png_data->size())); + if (report->include_screenshot && png_data) { + feedback_data->set_image(std::string(base::as_string_view(*png_data))); } // Append consent value to report. For cross platform implementations see:
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_screenshot_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_screenshot_job_unittest.cc index ee7d6e23..fa138ba5 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_screenshot_job_unittest.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_screenshot_job_unittest.cc
@@ -124,7 +124,7 @@ reinterpret_cast<const unsigned char*>(bmp.getPixels()), color_format, gfx::Size(bmp.width(), bmp.height()), static_cast<int>(bmp.rowBytes()), false, - std::vector<gfx::PNGCodec::Comment>(), &png_bytes->data())) { + std::vector<gfx::PNGCodec::Comment>(), &png_bytes->as_vector())) { LOG(ERROR) << "Failed to encode image"; } return png_bytes;
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_encrypted_event_reporter.cc b/chrome/browser/ash/policy/reporting/arc_app_install_encrypted_event_reporter.cc index d795de6..be5d31a 100644 --- a/chrome/browser/ash/policy/reporting/arc_app_install_encrypted_event_reporter.cc +++ b/chrome/browser/ash/policy/reporting/arc_app_install_encrypted_event_reporter.cc
@@ -47,6 +47,11 @@ auto android_app_install_event = std::make_unique<reporting::AndroidAppInstallEvent>( CreateAndroidAppInstallEvent(package, event)); + // TODO(b/334977181): Remove this log statement. It's just to debug TAST + // test flakiness. Enqueue status is purposefully blank because the test + // expects a regex match for " enqueue status = " + LOG(ERROR) << "Enqueued ARC install event: package = " << package + << " event type = " << event.event_type() << " enqueue status = "; report_queue_->Enqueue( std::move(android_app_install_event), reporting::Priority::BACKGROUND_BATCH, @@ -59,10 +64,9 @@ // are reported. LOG(ERROR) ensures that logs are written if (base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kArcInstallEventChromeLogForTests)) { - LOG(ERROR) - << "Enqueued ARC install event: package = " << package - << " event type = " << event_type - << " enqueue status = " << status; + LOG(ERROR) << "arc install event: package = " << package + << " event type = " << event_type + << " enqueue status = " << status; } }, package, event.event_type()));
diff --git a/chrome/browser/ash/printing/printer_info_cups.cc b/chrome/browser/ash/printing/printer_info_cups.cc index 32c094d..6e26821 100644 --- a/chrome/browser/ash/printing/printer_info_cups.cc +++ b/chrome/browser/ash/printing/printer_info_cups.cc
@@ -31,51 +31,6 @@ printing::PrinterStatus printer_status; }; -// Enums for Printing.CUPS.HighestIppVersion. Do not delete entries. Keep -// synced with enums.xml. Represents IPP versions 1.0, 1.1, 2.0, 2.1, and 2.2. -// Error is used if the version was unparsable. OutOfRange is used for values -// that are not currently mapped. -enum class IppVersion { - kError, - kUnknown, - k10, - k11, - k20, - k21, - k22, - kMaxValue = k22 -}; - -using MajorMinor = std::pair<uint32_t, uint32_t>; -using VersionEntry = std::pair<MajorMinor, IppVersion>; - -IppVersion ToIppVersion(const base::Version& version) { - constexpr std::array<VersionEntry, 5> kVersions = { - VersionEntry(MajorMinor((uint32_t)1, (uint32_t)0), IppVersion::k10), - VersionEntry(MajorMinor((uint32_t)1, (uint32_t)1), IppVersion::k11), - VersionEntry(MajorMinor((uint32_t)2, (uint32_t)0), IppVersion::k20), - VersionEntry(MajorMinor((uint32_t)2, (uint32_t)1), IppVersion::k21), - VersionEntry(MajorMinor((uint32_t)2, (uint32_t)2), IppVersion::k22)}; - - if (!version.IsValid()) { - return IppVersion::kError; - } - - const auto& components = version.components(); - if (components.size() != 2) { - return IppVersion::kError; - } - - const auto target = MajorMinor(components[0], components[1]); - const auto iter = base::ranges::find(kVersions, target, &VersionEntry::first); - - if (iter == kVersions.end()) { - return IppVersion::kUnknown; - } - - return iter->second; -} - // Returns true if any of the |ipp_versions| are greater than or equal to 2.0. bool AllowedIpp(const std::vector<base::Version>& ipp_versions) { return base::ranges::any_of(ipp_versions, [](const base::Version& version) { @@ -134,13 +89,6 @@ return; } - DCHECK(!printer_info.ipp_versions.empty()) - << "Properly queried PrinterInfo always has at least one version"; - base::UmaHistogramEnumeration( - "Printing.CUPS.HighestIppVersion", - ToIppVersion(*std::max_element(printer_info.ipp_versions.begin(), - printer_info.ipp_versions.end()))); - std::move(callback).Run(result, printer_status, printer_info.make_and_model, printer_info.document_formats, IsAutoconf(printer_info),
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc index fd52eaa..ea14c41 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc
@@ -428,7 +428,7 @@ // The BigBuffer data received from the observer should be equal to the test // image encoded to png. ASSERT_GT(expected_data.size(), 0u); - EXPECT_EQ(expected_data, encoded_png->data()); + EXPECT_EQ(expected_data, base::span(*encoded_png)); } TEST_F(PersonalizationAppUserProviderImplTest,
diff --git a/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_url_data_source.cc b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_url_data_source.cc index 17c7e26f..9e8bb79a 100644 --- a/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_url_data_source.cc +++ b/chrome/browser/ash/system_web_apps/test_support/test_system_web_app_url_data_source.cc
@@ -80,13 +80,13 @@ scoped_refptr<base::RefCountedString> ref_contents( new base::RefCountedString); if (id == "manifest.json") - ref_contents->data() = kManifestText; + ref_contents->as_string() = kManifestText; else if (id == "pwa.html") - ref_contents->data() = kPwaHtml; + ref_contents->as_string() = kPwaHtml; else if (id == "sw.js") - ref_contents->data() = kSwJs; + ref_contents->as_string() = kSwJs; else if (id == "page2.html") - ref_contents->data() = kPage2Html; + ref_contents->as_string() = kPage2Html; else NOTREACHED();
diff --git a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc index 516d241..33c88c0 100644 --- a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc +++ b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc
@@ -47,7 +47,7 @@ scoped_refptr<base::RefCountedBytes> EncodeImage(const gfx::ImageSkia& image) { auto output = base::MakeRefCounted<base::RefCountedBytes>(); SkBitmap bitmap = *(image.bitmap()); - gfx::JPEGCodec::Encode(bitmap, /*quality=*/90, &(output)->data()); + gfx::JPEGCodec::Encode(bitmap, /*quality=*/90, &(output)->as_vector()); return output; }
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsSizer.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsSizer.java index 274efb2..7590d43 100644 --- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsSizer.java +++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsSizer.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.browser_controls; +import androidx.annotation.ColorInt; + /** * Allows for sizing the browser controls, as well as manipulating visibility and retrieving state. */ @@ -16,7 +18,16 @@ /** * Sets whether the changes to the browser controls heights should be animated. + * * @param animateBrowserControlsHeightChanges True if the height changes should be animated. */ void setAnimateBrowserControlsHeightChanges(boolean animateBrowserControlsHeightChanges); + + /** + * Notifies the {@BrowserControlsSizer} of the background color that's been set to the browser + * controls view. + * + * @param color The color used for the background of the browser controls view. + */ + void notifyBackgroundColor(@ColorInt int color); }
diff --git a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java index e696cbe..bd08743 100644 --- a/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java +++ b/chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/BrowserControlsStateProvider.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.browser_controls; +import androidx.annotation.ColorInt; + /** An interface for retrieving and monitoring browser controls state. */ public interface BrowserControlsStateProvider { /** An observer to be notified of browser controls changes */ @@ -39,10 +41,14 @@ /** Called when the visibility of the controls container changes. */ default void onAndroidControlsVisibilityChanged(int visibility) {} + + /** Called when the background color of the controls container changes. */ + default void onBottomControlsBackgroundColorChanged(@ColorInt int color) {} } /** * Add an observer to be notified of browser controls events. + * * @param obs The observer to add. */ void addObserver(Observer obs);
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index e79f2abc..3cc047ea 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -102,6 +102,7 @@ #include "components/crash/core/common/crash_key.h" #include "components/embedder_support/origin_trials/origin_trials_settings_storage.h" #include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_constants.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/gcm_driver/gcm_driver.h" #include "components/language/core/browser/pref_names.h" #include "components/metrics/metrics_pref_names.h" @@ -1142,8 +1143,8 @@ BrowserProcessImpl::fingerprinting_protection_ruleset_service() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!created_fingerprinting_protection_ruleset_service_ && - base::FeatureList::IsEnabled( - features::kEnableFingerprintingProtectionBlocklist)) { + base::FeatureList::IsEnabled(fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter)) { CreateFingerprintingProtectionRulesetService(); } return fingerprinting_protection_ruleset_service_.get();
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index e746f0f..608b294 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -76,6 +76,7 @@ #include "chrome/browser/spellchecker/spellcheck_factory.h" #include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/sync/sync_service_factory.h" +#include "chrome/browser/tpcd/metadata/manager_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/ui/find_bar/find_bar_state.h" #include "chrome/browser/ui/find_bar/find_bar_state_factory.h" @@ -125,6 +126,7 @@ #include "components/search_engines/template_url_service.h" #include "components/sync/service/sync_service.h" #include "components/sync/service/sync_user_settings.h" +#include "components/tpcd/metadata/manager.h" #include "components/web_cache/browser/web_cache_manager.h" #include "components/webrtc_logging/browser/log_cleanup.h" #include "components/webrtc_logging/browser/text_log_list.h" @@ -658,6 +660,11 @@ base::Unretained(this), TracingDataType::kCookies)); safe_browsing::VerdictCacheManagerFactory::GetForProfile(profile_) ->OnCookiesDeleted(); + + if (tpcd::metadata::Manager* manager = + tpcd::metadata::ManagerFactory::GetForProfile(profile_)) { + manager->ResetCohorts(website_settings_filter); + } } if (filter_builder->GetMode() ==
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index f60e867..0f0a1c7 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -6,6 +6,7 @@ #include <stdint.h> +#include <memory> #include <set> #include <string> #include <utility> @@ -78,6 +79,7 @@ #include "chrome/browser/storage/durable_storage_permission_context.h" #include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" #include "chrome/browser/sync/sync_service_factory.h" +#include "chrome/browser/tpcd/metadata/manager_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/trusted_vault/trusted_vault_service_factory.h" #include "chrome/browser/webdata_services/web_data_service_factory.h" @@ -153,6 +155,10 @@ #include "components/site_engagement/content/site_engagement_service.h" #include "components/site_isolation/pref_names.h" #include "components/sync/test/test_sync_service.h" +#include "components/tpcd/metadata/manager.h" +#include "components/tpcd/metadata/parser.h" +#include "components/tpcd/metadata/parser_test_helper.h" +#include "components/tpcd/metadata/prefs.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/background_tracing_manager.h" #include "content/public/browser/browser_context.h" @@ -168,6 +174,7 @@ #include "content/public/test/mock_download_manager.h" #include "content/public/test/test_utils.h" #include "mojo/public/cpp/bindings/remote.h" +#include "net/base/features.h" #include "net/base/isolation_info.h" #include "net/base/network_anonymization_key.h" #include "net/cookies/canonical_cookie.h" @@ -753,6 +760,41 @@ raw_ptr<permissions::PermissionDecisionAutoBlocker> autoblocker_; }; +class RemoveTpcdMetadataCohortsTester { + public: + explicit RemoveTpcdMetadataCohortsTester(TestingProfile* profile) { + det_generator_ = new tpcd::metadata::DeterministicGenerator(); + tpcd::metadata::RegisterLocalStatePrefs(local_state_.registry()); + manager_ = tpcd::metadata::ManagerFactory::GetForProfile(profile); + manager_->SetRandGeneratorForTesting(det_generator_); + manager_->SetPrefServiceForTesting(&local_state_); + } + ~RemoveTpcdMetadataCohortsTester() { + det_generator_ = nullptr; + manager_ = nullptr; + } + + RemoveTpcdMetadataCohortsTester(const RemoveTpcdMetadataCohortsTester&) = + delete; + RemoveTpcdMetadataCohortsTester& operator=( + const RemoveTpcdMetadataCohortsTester&) = delete; + + tpcd::metadata::Parser* GetParser() { + return tpcd::metadata::Parser::GetInstance(); + } + + tpcd::metadata::Manager* GetManager() { return manager_; } + + tpcd::metadata::DeterministicGenerator* GetDetGenerator() { + return det_generator_; + } + + private: + raw_ptr<tpcd::metadata::Manager> manager_; + raw_ptr<tpcd::metadata::DeterministicGenerator> det_generator_; + TestingPrefServiceSimple local_state_; +}; + // Custom matcher to test the equivalence of two URL filters. Since those are // blackbox predicates, we can only approximate the equivalence by testing // whether the filter give the same answer for several URLs. This is currently @@ -4389,3 +4431,164 @@ EXPECT_EQ(salt2c, salt2b); EXPECT_EQ(salt3c, salt3b); } + +class ChromeBrowsingDataRemoverDelegateTpcdMetadataTest + : public ChromeBrowsingDataRemoverDelegateTest { + public: + ChromeBrowsingDataRemoverDelegateTpcdMetadataTest() { + feature_list_.InitWithFeatures({net::features::kTpcdMetadataStagedRollback}, + {}); + } +}; + +TEST_F(ChromeBrowsingDataRemoverDelegateTpcdMetadataTest, ResetAllCohorts) { + auto tester = RemoveTpcdMetadataCohortsTester(GetProfile()); + + const std::string primary_pattern_spec = "https://example1.com"; + const std::string primary_pattern_spec_2 = "https://example2.com"; + const std::string secondary_pattern_spec = "https://example3.com"; + + // dtrp is arbitrary here, selected between (0,100). + const uint32_t dtrp = 10; + tpcd::metadata::Metadata metadata; + tpcd::metadata::helpers::AddEntryToMetadata( + metadata, primary_pattern_spec, secondary_pattern_spec, + tpcd::metadata::Parser::kSource1pDt, dtrp); + tpcd::metadata::helpers::AddEntryToMetadata( + metadata, primary_pattern_spec_2, secondary_pattern_spec, + tpcd::metadata::Parser::kSource1pDt, dtrp); + + // Establish grant with deterministic cohorts. + { + // rand is set as-is here to guarantee GRACE_PERIOD_FORCED_ON. + uint32_t rand = dtrp + 1; + tester.GetDetGenerator()->set_rand(rand); + + tester.GetParser()->ParseMetadata(metadata.SerializeAsString()); + + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + } + + // Make sure the cohorts are persisted. + { + // rand is set as-is here to guarantee GRACE_PERIOD_FORCED_OFF. + uint32_t rand = dtrp; + tester.GetDetGenerator()->set_rand(rand); + + tester.GetParser()->ParseMetadata(metadata.SerializeAsString()); + + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + } + + // Apply deletion of cookies. + BlockUntilBrowsingDataRemoved(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_COOKIES, + false); + + // Make sure the cohorts was reset. + { + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_OFF); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_OFF); + } +} + +TEST_F(ChromeBrowsingDataRemoverDelegateTpcdMetadataTest, ResetOneCohort) { + auto tester = RemoveTpcdMetadataCohortsTester(GetProfile()); + + const std::string primary_pattern_spec = "https://example1.com"; + const std::string primary_pattern_spec_2 = "https://example2.com"; + const std::string secondary_pattern_spec = "https://example3.com"; + + // dtrp is arbitrary here, selected between (0,100). + const uint32_t dtrp = 10; + tpcd::metadata::Metadata metadata; + tpcd::metadata::helpers::AddEntryToMetadata( + metadata, primary_pattern_spec, secondary_pattern_spec, + tpcd::metadata::Parser::kSource1pDt, dtrp); + tpcd::metadata::helpers::AddEntryToMetadata( + metadata, primary_pattern_spec_2, secondary_pattern_spec, + tpcd::metadata::Parser::kSource1pDt, dtrp); + + // Establish grant with deterministic cohorts. + { + // rand is set as-is here to guarantee GRACE_PERIOD_FORCED_ON. + uint32_t rand = dtrp + 1; + tester.GetDetGenerator()->set_rand(rand); + + tester.GetParser()->ParseMetadata(metadata.SerializeAsString()); + + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + } + + // Make sure the cohorts are persisted. + { + // rand is set as-is here to guarantee GRACE_PERIOD_FORCED_OFF. + uint32_t rand = dtrp; + tester.GetDetGenerator()->set_rand(rand); + + tester.GetParser()->ParseMetadata(metadata.SerializeAsString()); + + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + } + + // Apply deletion of cookies. + std::unique_ptr<BrowsingDataFilterBuilder> filter( + BrowsingDataFilterBuilder::Create( + BrowsingDataFilterBuilder::Mode::kDelete)); + filter->AddRegisterableDomain(GURL(primary_pattern_spec).host()); + BlockUntilOriginDataRemoved(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_COOKIES, + std::move(filter)); + + // Make sure only one cohort was reset. + { + EXPECT_EQ( + tester.GetManager() + ->GetGrants() + .front() + .metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_OFF); + EXPECT_EQ( + tester.GetManager()->GetGrants().back().metadata.tpcd_metadata_cohort(), + content_settings::mojom::TpcdMetadataCohort::GRACE_PERIOD_FORCED_ON); + } +}
diff --git a/chrome/browser/component_updater/DEPS b/chrome/browser/component_updater/DEPS index be09640..49e0799 100644 --- a/chrome/browser/component_updater/DEPS +++ b/chrome/browser/component_updater/DEPS
@@ -3,6 +3,7 @@ "+chrome/elevation_service", "+chrome/browser/share", "+chrome/updater", + "+components/fingerprinting_protection_filter/browser", "+components/tpcd/metadata", "+components/fingerprinting_protection_filter", "+components/cdm/common",
diff --git a/chrome/browser/component_updater/afp_blocked_domain_list_component_installer.cc b/chrome/browser/component_updater/afp_blocked_domain_list_component_installer.cc index a8d2d60..2fbaac24 100644 --- a/chrome/browser/component_updater/afp_blocked_domain_list_component_installer.cc +++ b/chrome/browser/component_updater/afp_blocked_domain_list_component_installer.cc
@@ -22,6 +22,7 @@ #include "chrome/common/chrome_features.h" #include "components/component_updater/component_updater_paths.h" #include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_constants.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/subresource_filter/content/shared/browser/ruleset_service.h" #include "components/subresource_filter/core/browser/subresource_filter_constants.h" @@ -140,7 +141,8 @@ void RegisterAntiFingerprintingBlockedDomainListComponent( ComponentUpdateService* cus) { if (!base::FeatureList::IsEnabled( - features::kEnableFingerprintingProtectionBlocklist)) { + fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter)) { return; }
diff --git a/chrome/browser/component_updater/afp_blocked_domain_list_component_installer_unittest.cc b/chrome/browser/component_updater/afp_blocked_domain_list_component_installer_unittest.cc index b0cd529..52304116 100644 --- a/chrome/browser/component_updater/afp_blocked_domain_list_component_installer_unittest.cc +++ b/chrome/browser/component_updater/afp_blocked_domain_list_component_installer_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "components/component_updater/mock_component_updater_service.h" #include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_constants.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/prefs/testing_pref_service.h" #include "components/subresource_filter/content/shared/browser/ruleset_service.h" #include "components/subresource_filter/core/browser/ruleset_version.h" @@ -169,7 +170,8 @@ ComponentRegistration_FeatureEnabled) { base::test::ScopedFeatureList scoped_enable; scoped_enable.InitAndEnableFeature( - features::kEnableFingerprintingProtectionBlocklist); + fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter); auto service = std::make_unique<component_updater::MockComponentUpdateService>(); @@ -184,7 +186,8 @@ ComponentRegistration_FeatureDisabled) { base::test::ScopedFeatureList scoped_disable; scoped_disable.InitAndDisableFeature( - features::kEnableFingerprintingProtectionBlocklist); + fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter); auto service = std::make_unique<component_updater::MockComponentUpdateService>();
diff --git a/chrome/browser/data_sharing/BUILD.gn b/chrome/browser/data_sharing/BUILD.gn index ee03584..a45987d6 100644 --- a/chrome/browser/data_sharing/BUILD.gn +++ b/chrome/browser/data_sharing/BUILD.gn
@@ -14,9 +14,9 @@ sources = [ "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactory.java" ] deps = [ + ":ui_delegate_java", "//base:base_java", "//build/android:build_java", - "//chrome/browser/data_sharing/android:ui_delegate_java", "//chrome/browser/profiles/android:java", "//components/data_sharing/public:public_java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -38,30 +38,56 @@ android_library("java") { resources_package = "org.chromium.chrome.browser.data_sharing" sources = [ - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogCoordinator.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogMediator.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingNotificationManager.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesCoordinator.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesMediator.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesProperties.java", - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesViewBinder.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogCoordinator.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogMediator.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingNotificationManager.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegateImpl.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesCoordinator.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesMediator.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesProperties.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/SharedImageTilesViewBinder.java", ] deps = [ ":java_resources", "//base:base_java", + "//base:base_java", "//chrome/browser/android/intents:java", "//chrome/browser/notifications:java", + "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/browser_ui/notifications/android:java", "//components/browser_ui/styles/android:java_resources", "//third_party/android_sdk:android_window_extensions_java", + "//third_party/androidx:androidx_annotation_annotation_java", "//ui/android:ui_no_recycler_view_java", ] + + public_deps = [ ":ui_delegate_java" ] + } + + android_library("ui_delegate_java") { + sources = [ + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegate.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegateImpl.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/configs/AvatarConfig.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/configs/GroupMemberConfig.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/configs/MemberPickerConfig.java", + ] + + deps = [ + "//base:base_java", + "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] + + jar_excluded_patterns = [ "*/DataSharingUIDelegateImpl.class" ] } robolectric_library("junit") { - sources = [ "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingNotificationManagerUnitTest.java" ] + sources = [ "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingNotificationManagerUnitTest.java" ] deps = [ ":java", "//base:base_java", @@ -78,7 +104,7 @@ testonly = true sources = [ - "//chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogTest.java", + "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingInvitationDialogTest.java", "android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingServiceFactoryTest.java", ] deps = [
diff --git a/chrome/browser/data_sharing/android/BUILD.gn b/chrome/browser/data_sharing/android/BUILD.gn deleted file mode 100644 index b2efe60..0000000 --- a/chrome/browser/data_sharing/android/BUILD.gn +++ /dev/null
@@ -1,38 +0,0 @@ -# Copyright 2024 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/config.gni") -import("//build/config/android/rules.gni") - -android_library("java") { - sources = [ "java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegateImpl.java" ] - - deps = [ - "//base:base_java", - "//chrome/browser/profiles/android:java", - "//chrome/browser/tab:java", - "//third_party/androidx:androidx_annotation_annotation_java", - ] - - public_deps = [ ":ui_delegate_java" ] -} - -android_library("ui_delegate_java") { - sources = [ - "java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegate.java", - "java/src/org/chromium/chrome/browser/data_sharing/DataSharingUIDelegateImpl.java", - "java/src/org/chromium/chrome/browser/data_sharing/configs/AvatarConfig.java", - "java/src/org/chromium/chrome/browser/data_sharing/configs/GroupMemberConfig.java", - "java/src/org/chromium/chrome/browser/data_sharing/configs/MemberPickerConfig.java", - ] - - deps = [ - "//base:base_java", - "//chrome/browser/profiles/android:java", - "//chrome/browser/tab:java", - "//third_party/androidx:androidx_annotation_annotation_java", - ] - - jar_excluded_patterns = [ "*/DataSharingUIDelegateImpl.class" ] -}
diff --git a/chrome/browser/devtools/device/usb/android_usb_device.cc b/chrome/browser/devtools/device/usb/android_usb_device.cc index cce1739..b570d4d 100644 --- a/chrome/browser/devtools/device/usb/android_usb_device.cc +++ b/chrome/browser/devtools/device/usb/android_usb_device.cc
@@ -286,9 +286,13 @@ // Queue body. if (!message->body.empty()) { auto body_buffer = base::MakeRefCounted<base::RefCountedBytes>(body_length); - memcpy(body_buffer->front(), message->body.data(), message->body.length()); - if (append_zero) - body_buffer->data()[body_length - 1] = 0; + { + auto& v = body_buffer->as_vector(); + memcpy(v.data(), message->body.data(), message->body.length()); + if (append_zero) { + v[body_length - 1] = 0; + } + } outgoing_queue_.push(body_buffer); if (android_device_info_.zero_mask && (body_length & android_device_info_.zero_mask) == 0) { @@ -307,10 +311,10 @@ BulkMessage message = outgoing_queue_.front(); outgoing_queue_.pop(); - DumpMessage(true, message->front(), message->size()); + DumpMessage(true, message->data(), message->size()); device_->GenericTransferOut( - android_device_info_.outbound_address, message->data(), kUsbTimeout, + android_device_info_.outbound_address, message->as_vector(), kUsbTimeout, base::BindOnce(&AndroidUsbDevice::OutgoingMessageSent, weak_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/devtools/protocol/autofill_handler.cc b/chrome/browser/devtools/protocol/autofill_handler.cc index caf2014c..97ed29bb 100644 --- a/chrome/browser/devtools/protocol/autofill_handler.cc +++ b/chrome/browser/devtools/protocol/autofill_handler.cc
@@ -281,8 +281,8 @@ : u""; filled_fields_to_be_sent_to_devtools->push_back( protocol::Autofill::FilledField::Create() - .SetId(base::UTF16ToUTF8(autofill_field->id_attribute)) - .SetName(base::UTF16ToUTF8(autofill_field->name_attribute)) + .SetId(base::UTF16ToUTF8(autofill_field->id_attribute())) + .SetName(base::UTF16ToUTF8(autofill_field->name_attribute())) .SetValue(base::UTF16ToUTF8(filled_value)) .SetHtmlType(std::string(autofill::FormControlTypeToString( autofill_field->form_control_type())))
diff --git a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc index d32dae7..e4e552e 100644 --- a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc +++ b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
@@ -480,11 +480,11 @@ form.renderer_id = form_id().renderer_id; form.fields.push_back(test::CreateTestFormField( /*label=*/"", "name_1", "value_1", FormControlType::kInputText)); - form.fields.back().id_attribute = u"id_1"; + form.fields.back().set_id_attribute(u"id_1"); form.fields.back().host_frame = form.host_frame; form.fields.push_back(test::CreateTestFormField( /*label=*/"", "name_2", "value_2", FormControlType::kInputText)); - form.fields.back().id_attribute = u"id_2"; + form.fields.back().set_id_attribute(u"id_2"); form.fields.back().host_frame = form.host_frame; // The parsed form is queried by @@ -549,7 +549,8 @@ const FormFieldData* ffd = filled_fields_by_autofill[i]; const AutofillField* af = fs.GetFieldById(ffd->global_id()); - EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16("id", af->id_attribute)); + EXPECT_THAT(ff, + FilledFieldHasAttributeWithValue16("id", af->id_attribute())); EXPECT_THAT(ff, FilledFieldHasAttributeWithValue( "autofillType", std::string(FieldTypeToDeveloperRepresentationString( @@ -566,8 +567,8 @@ FilledFieldHasAttributeWithValue( "htmlType", std::string(autofill::FormControlTypeToString( af->form_control_type())))); - EXPECT_THAT(ff, - FilledFieldHasAttributeWithValue16("name", af->name_attribute)); + EXPECT_THAT( + ff, FilledFieldHasAttributeWithValue16("name", af->name_attribute())); EXPECT_EQ(*ff.GetDict().FindIntByDottedPath("fieldId"), (int)(ffd->renderer_id().value())); }
diff --git a/chrome/browser/enterprise/data_protection/print_utils.cc b/chrome/browser/enterprise/data_protection/print_utils.cc index 3f5246c..424275a 100644 --- a/chrome/browser/enterprise/data_protection/print_utils.cc +++ b/chrome/browser/enterprise/data_protection/print_utils.cc
@@ -130,7 +130,7 @@ std::move(on_verdict).Run(/*allowed=*/true); return; } - std::memcpy(region.mapping.memory(), print_data->front(), print_data->size()); + std::memcpy(region.mapping.memory(), print_data->data(), print_data->size()); scanning_data.page = std::move(region.region); auto on_scan_result = base::BindOnce(
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc index 5bc42af..2a9fbdc 100644 --- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc +++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -13,6 +13,7 @@ #include <vector> #include "base/check.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -241,6 +242,12 @@ return false; } net_partition_key = key.value(); + // Record 'well formatted' uma here so that we count only coercible + // partition keys. + base::UmaHistogramBoolean( + "Extensions.CookieAPIPartitionKeyWellFormatted", + net::SchemefulSite::Deserialize(partition_key->top_level_site.value()) + .Serialize() == partition_key->top_level_site.value()); } return true; }
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc index 998506a..046bc905 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -922,10 +922,7 @@ std::string ExtensionInfoGenerator::GetIconUrlFromImage( const gfx::Image& image) { - scoped_refptr<base::RefCountedMemory> data; - data = image.As1xPNGBytes(); - std::string base_64 = base::Base64Encode( - std::string_view(data->front_as<char>(), data->size())); + std::string base_64 = base::Base64Encode(*image.As1xPNGBytes()); const char kDataUrlPrefix[] = "data:image/png;base64,"; return GURL(kDataUrlPrefix + base_64).spec(); }
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc index acc63592..bf3f93a 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc +++ b/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
@@ -107,14 +107,9 @@ WaitForFileCleanup(&delegate); } -// TODO(crbug.com/326868086): Test is flaky on UBSan and MSan. -#if defined(UNDEFINED_SANITIZER) || defined(MEMORY_SANITIZER) -#define MAYBE_SaveAsMHTMLWithFileAccess DISABLED_SaveAsMHTMLWithFileAccess -#else -#define MAYBE_SaveAsMHTMLWithFileAccess SaveAsMHTMLWithFileAccess -#endif +// TODO(crbug.com/326868086): Test is flaky. IN_PROC_BROWSER_TEST_P(ExtensionPageCaptureApiTest, - MAYBE_SaveAsMHTMLWithFileAccess) { + DISABLED_SaveAsMHTMLWithFileAccess) { ASSERT_TRUE(StartEmbeddedTestServer()); PageCaptureSaveAsMHTMLDelegate delegate; ASSERT_TRUE(RunTest("page_capture", /*custom_arg=*/nullptr,
diff --git a/chrome/browser/extensions/api/user_scripts/user_scripts_apitest.cc b/chrome/browser/extensions/api/user_scripts/user_scripts_apitest.cc index 471fe7e..c7148d97 100644 --- a/chrome/browser/extensions/api/user_scripts/user_scripts_apitest.cc +++ b/chrome/browser/extensions/api/user_scripts/user_scripts_apitest.cc
@@ -73,8 +73,10 @@ /*disabled_features=*/{}); } -// TODO(crbug.com/40935741): Flaky on Linux debug. -#if BUILDFLAG(IS_LINUX) && !defined(NDEBUG) +// TODO(crbug.com/40935741, crbug.com/335421977): Flaky on Linux debug and on +// "Linux ChromiumOS MSan Tests". +#if (BUILDFLAG(IS_LINUX) && !defined(NDEBUG)) || \ + (BUILDFLAG(IS_CHROMEOS) && defined(MEMORY_SANITIZER)) #define MAYBE_RegisterUserScripts DISABLED_RegisterUserScripts #else #define MAYBE_RegisterUserScripts RegisterUserScripts @@ -95,7 +97,13 @@ ASSERT_TRUE(RunExtensionTest("user_scripts/update")) << message_; } -IN_PROC_BROWSER_TEST_F(UserScriptsAPITest, ConfigureWorld) { +// TODO(crbug.com/335421977): Flaky on "Linux ChromiumOS MSan Tests". +#if BUILDFLAG(IS_CHROMEOS) && defined(MEMORY_SANITIZER) +#define MAYBE_ConfigureWorld DISABLED_ConfigureWorld +#else +#define MAYBE_ConfigureWorld ConfigureWorld +#endif +IN_PROC_BROWSER_TEST_F(UserScriptsAPITest, MAYBE_ConfigureWorld) { ASSERT_TRUE(RunExtensionTest("user_scripts/configure_world")) << message_; }
diff --git a/chrome/browser/extensions/chrome_url_request_util.cc b/chrome/browser/extensions/chrome_url_request_util.cc index 14e8c038..754c77f 100644 --- a/chrome/browser/extensions/chrome_url_request_util.cc +++ b/chrome/browser/extensions/chrome_url_request_util.cc
@@ -49,8 +49,7 @@ base::CompareCase::INSENSITIVE_ASCII)) { // All of our HTML files should be UTF-8 and for other resource types // (like images), charset doesn't matter. - DCHECK(base::IsStringUTF8(base::StringPiece( - reinterpret_cast<const char*>(data->front()), data->size()))); + DCHECK(base::IsStringUTF8(base::as_string_view(*data))); *out_charset = "utf-8"; } } @@ -69,9 +68,8 @@ : nullptr; if (replacements) { - base::StringPiece input(reinterpret_cast<const char*>(bytes->front()), - bytes->size()); - std::string temp_str = ui::ReplaceTemplateExpressions(input, *replacements); + std::string temp_str = ui::ReplaceTemplateExpressions( + base::as_string_view(*bytes), *replacements); DCHECK(!temp_str.empty()); return base::MakeRefCounted<base::RefCountedString>(std::move(temp_str)); } else { @@ -183,7 +181,7 @@ std::nullopt); size_t write_size = data->size(); - MojoResult result = producer_handle->WriteData(data->front(), &write_size, + MojoResult result = producer_handle->WriteData(data->data(), &write_size, MOJO_WRITE_DATA_FLAG_NONE); OnFileWritten(result); }
diff --git a/chrome/browser/extensions/extension_fullscreen_apitest.cc b/chrome/browser/extensions/extension_fullscreen_apitest.cc index f0764f3..08baa73 100644 --- a/chrome/browser/extensions/extension_fullscreen_apitest.cc +++ b/chrome/browser/extensions/extension_fullscreen_apitest.cc
@@ -53,15 +53,9 @@ ASSERT_TRUE(browser()->window()->IsFullscreen()); } -#if BUILDFLAG(IS_MAC) -// Fails flakily on Mac: http://crbug.com/308041 -#define MAYBE_UpdateWindowSizeExitsFullscreen \ - DISABLED_UpdateWindowSizeExitsFullscreen -#else -#define MAYBE_UpdateWindowSizeExitsFullscreen UpdateWindowSizeExitsFullscreen -#endif // BUILDFLAG(IS_MAC) +// Fails flakily: crbug.com/335640705. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, - MAYBE_UpdateWindowSizeExitsFullscreen) { + DISABLED_UpdateWindowSizeExitsFullscreen) { browser()->exclusive_access_manager()->context()->EnterFullscreen( GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, display::kInvalidDisplayId);
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index 8352344e..41451fdc 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -275,7 +275,7 @@ for (const gfx::ImageSkiaRep& image_rep : image_reps) { auto bitmap_data = base::MakeRefCounted<base::RefCountedBytes>(); if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.GetBitmap(), false, - &bitmap_data->data())) { + &bitmap_data->as_vector())) { favicon_base::FaviconRawBitmapResult bitmap_result; bitmap_result.bitmap_data = bitmap_data; bitmap_result.pixel_size = gfx::Size(image_rep.pixel_width(),
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index af104e02..3835783 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -162,7 +162,7 @@ { "name": "android-hats-refactor", "owners": [ "wenyufu@chromium.org", "clank-app-team@google.com" ], - "expiry_milestone": 124 + "expiry_milestone": 128 }, { "name": "android-hub", @@ -807,7 +807,7 @@ { "name": "autofill-enable-virtual-cards", "owners": [ "siyua@chromium.org", "chbannon@google.com", "slobodan@chromium.org" ], - "expiry_milestone": 125 + "expiry_milestone": 128 }, { "name": "autofill-enable-xhr-submission-detection-ios", @@ -1487,11 +1487,6 @@ "expiry_milestone": 125 }, { - "name": "context-menu-popup-for-all-screen-sizes", - "owners": ["wenyufu@chromium.org", "clank-large-form-factors@google.com"], - "expiry_milestone": 112 - }, - { "name": "contextual-nudges", "owners": [ "yulunwu@chromium.org" ], "expiry_milestone": 83 @@ -1598,8 +1593,8 @@ }, { "name": "cros-components", - "owners": [ "cros-jellybean-team@google.com"], - "expiry_milestone": 125 + "owners": [ "wenbojie@chromium.com"], + "expiry_milestone": 137 }, { "name": "cros-focus-mode", @@ -2117,6 +2112,11 @@ "expiry_milestone": 125 }, { + "name": "drive-fs-mirroring", + "owners": [ "wenbojie@chromium.org", "fdegros@chromium.org", "simmonsjosh@google.com"], + "expiry_milestone": 133 + }, + { "name": "drive-fs-show-cse-files", "owners": [ "cros-dlp-extended@google.com" ], "expiry_milestone": 135 @@ -2139,7 +2139,7 @@ { "name": "dynamic-top-chrome", "owners": ["wenyufu@chromium.org", "clank-large-form-factors@google.com"], - "expiry_milestone": 126 + "expiry_milestone": 128 }, { "name": "eap-gtc-wifi-authentication", @@ -2361,6 +2361,11 @@ "expiry_milestone": 129 }, { + "name": "enable-automatic-shared-image-management", + "owners": [ "mjzhang@chromium.org", "vasilyt@chromium.org" ], + "expiry_milestone": 128 + }, + { "name": "enable-background-blur", "owners": [ "newcomer@chromium.org" ], "expiry_milestone": 86 @@ -4821,11 +4826,6 @@ "expiry_milestone": 125 }, { - "name": "history-journeys-include-synced-visits", - "owners": [ "tommycli@chromium.org", "chrome-journeys@google.com" ], - "expiry_milestone": 125 - }, - { "name": "history-journeys-show-all-clusters", "owners": [ "sophiechang@chromium.org", "chrome-journeys@google.com", "chrome-intelligence-core@google.com" ], "expiry_milestone": 125 @@ -5425,11 +5425,6 @@ "expiry_milestone": 135 }, { - "name": "legacy-tech-report-enable-cookie-issue-reports", - "owners": ["sandormajor@google.com", "zmin@chromium.org", "parastoog@chromium.org"], - "expiry_milestone": 125 - }, - { "name": "link-cross-device-internals", "owners": [ "chromeos-cross-device-eng@google.com", "dclasson@chromium.org" ], "expiry_milestone": 125 @@ -6652,6 +6647,11 @@ "expiry_milestone": 130 }, { + "name": "pdf-ink2", + "owners": [ "andyphan@chromium.org", "awscreen@chromium.org", "thestig@chromium.org" ], + "expiry_milestone": 134 + }, + { "name": "pdf-ocr", "owners": [ "rhalavati@chromium.org", "//ui/accessibility/OWNERS" ], "expiry_milestone": 130 @@ -6790,6 +6790,13 @@ "expiry_milestone": 130 }, { + "name": "print-preview-cros-primary", + "owners": [ + "//ash/webui/print_preview_cros/OWNERS" + ], + "expiry_milestone": 130 + }, + { "name": "print-preview-setup-assistance", "owners": [ "//ash/webui/print_management/OWNERS", @@ -7538,12 +7545,7 @@ "expiry_milestone": 130 }, { - "name": "shimless-rma-sku-description", - "owners": [ "zentaro@chromium.org", "gavinwill@chromium.org", "chenghan@chromium.org", "cros-peripherals@google.com", "cros-shimless-tpe-eng@google.com" ], - "expiry_milestone": 124 - }, - { - "name": "shopping-icon-color-variant", + "name": "shopping-icon-color-variant", "owners": [ "josephjoopark@chromium.org", "chrome-desktop-ui-sea@google.com" ], "expiry_milestone": 126 }, @@ -7965,6 +7967,11 @@ "expiry_milestone": 110 }, { + "name": "tab-strip-group-collapse-android", + "owners": [ "nemco@google.com", "zheliooo@google.com", "clank-large-form-factors@google.com" ], + "expiry_milestone": 135 + }, + { "name": "tab-strip-group-indicators-android", "owners": [ "twellington@google.com", "nemco@google.com", "zheliooo@google.com" ], "expiry_milestone": 130
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index da5d7bb..891daa7 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -38,24 +38,6 @@ const char kAcceleratedVideoEncodeDescription[] = "Hardware-accelerated video encode where available."; -#if BUILDFLAG(ENABLE_PDF) -const char kAccessiblePDFFormName[] = "Accessible PDF Forms"; -const char kAccessiblePDFFormDescription[] = - "Enables accessibility support for PDF forms."; - -const char kPdfOopifName[] = "OOPIF for PDF Viewer"; -const char kPdfOopifDescription[] = - "Use an OOPIF for the PDF Viewer, instead of a GuestView."; - -const char kPdfPortfolioName[] = "PDF portfolio"; -const char kPdfPortfolioDescription[] = "Enable PDF portfolio feature."; - -const char kPdfUseSkiaRendererName[] = "Use Skia Renderer"; -const char kPdfUseSkiaRendererDescription[] = - "Use Skia as the PDF renderer. This flag will have no effect if the " - "renderer choice is controlled by an enterprise policy."; -#endif - const char kAppDeduplicationServiceFondueName[] = "Identify duplicate app groups."; const char kAppDeduplicationServiceFondueDescription[] = @@ -1560,6 +1542,12 @@ "over, out events) tracks DOM node removal to fix event pairing on " "ancestor nodes."; +const char kEnableAutomaticSharedImageManagementName[] = + "Enable automatic shared image management"; +const char kEnableAutomaticSharedImageManagementDescription[] = + "When enabled, allows the shared image lifetime to be automatically " + "managed via ClientSharedImage."; + const char kEnableCssSelectorFragmentAnchorName[] = "Enables CSS selector fragment anchors"; const char kEnableCssSelectorFragmentAnchorDescription[] = @@ -2186,11 +2174,6 @@ const char kJourneysShowAllClustersDescription[] = "Enables all Journeys clusters to be shown on prominent UI surfaces"; -const char kJourneysIncludeSyncedVisitsName[] = - "History Journeys Include SyncedVisits"; -const char kJourneysIncludeSyncedVisitsDescription[] = - "Enabled synced visits to be included in History Journeys clusters."; - const char kJourneysZeroStateFilteringName[] = "History Journeys Zero-State Filtering"; const char kJourneysZeroStateFilteringDescription[] = @@ -2207,12 +2190,6 @@ const char kLargeFaviconFromGoogleDescription[] = "Request large favicons from Google's favicon service"; -const char kLegacyTechReportEnableCookieIssueReportsName[] = - "Enable reporting of Cookie Issues for legacy technology report"; -const char kLegacyTechReportEnableCookieIssueReportsDescription[] = - "When enabled, usage of third-party cookies (on allowlisted pages) is " - "uploaded for enterprise users as part of a legacy technology report."; - const char kLegacyTechReportTopLevelUrlName[] = "Using top level navigation URL for legacy technology report"; const char kLegacyTechReportTopLevelUrlDescription[] = @@ -2781,9 +2758,8 @@ const char kPasswordManagerShadowDomSupportDescription[] = "Enables form filling and saving for password forms in shadow DOM."; -extern const char kPasswordManualFallbackAvailableName[] = - "Password manual fallback"; -extern const char kPasswordManualFallbackAvailableDescription[] = +const char kPasswordManualFallbackAvailableName[] = "Password manual fallback"; +const char kPasswordManualFallbackAvailableDescription[] = "Enables triggering password suggestions through the context menu"; const char kPasswordParsingOnSaveUsesPredictionsName[] = @@ -3981,14 +3957,6 @@ "Migrates TabState from a pickle based schema to a FlatBuffer based " "schema."; -const char kContextMenuPopupForAllScreenSizesName[] = - "Context menu popup for all screen sizes"; -const char kContextMenuPopupForAllScreenSizesDescription[] = - "When disabled, context menu will be shown as pop-up window only for " - "devices in tablet mode, while shown as a fullscreen dialog for mobile " - "devices; when enabled, context menu will be shown as a pop-up window " - "for all form factors regardless of the screen sizes."; - const char kContextualSearchSuppressShortViewName[] = "Contextual Search suppress short view"; const char kContextualSearchSuppressShortViewDescription[] = @@ -4135,10 +4103,6 @@ const char kInfoCardAcknowledgementTrackingDescription[] = "Enable acknowledgement tracking for info cards."; -const char kInstantStartName[] = "Instant start"; -const char kInstantStartDescription[] = - "Show start surface before native library is loaded."; - const char kInterestFeedV2Name[] = "Interest Feed v2"; const char kInterestFeedV2Description[] = "Show content suggestions on the New Tab Page and Start Surface using the " @@ -4440,6 +4404,14 @@ const char kTabResumptionModuleAndroidDescription[] = "Enable showing tab suggestions on Android"; +const char kTabStripGroupCollapseAndroidName[] = + "Tab Strip Group Collapse Android"; +const char kTabStripGroupCollapseAndroidDescription[] = + "Enables tab strip group indicators to be clicked to collapse, temporarily " + "hiding the colored outline, the group title, and the grouped tabs. " + "Collapsed groups can be clicked again to expand. Synced tab groups will " + "immediately be collapsed."; + const char kTabStripGroupIndicatorsAndroidName[] = "Tab Strip Group Indicators Android"; const char kTabStripGroupIndicatorsAndroidDescription[] = @@ -5488,7 +5460,9 @@ const char kApnPoliciesName[] = "APN Policies"; const char kApnPoliciesDescription[] = "Enables the ChromeOS APN Policies, which gives admins the ability to set " - "APN policies for managed eSIM networks and pSIMs."; + "APN policies for managed eSIM networks and pSIMs. Note that the 'APN " + "Revamp' flag should be enabled as well for this feature to work as " + "expected."; const char kApnRevampName[] = "APN Revamp"; const char kApnRevampDescription[] = @@ -6152,6 +6126,10 @@ "permissions in the quick settings menu. Website notification permissions " "settings will be migrated to the lacros - chrome browser."; +const char kDriveFsMirroringName[] = "Enable local to Drive mirror sync"; +const char kDriveFsMirroringDescription[] = + "Enable mirror sync between local files and Google Drive"; + const char kDriveFsShowCSEFilesName[] = "Enable listing of CSE files"; const char kDriveFsShowCSEFilesDescription[] = "Enable listing of CSE files in DriveFS, which will result in these files " @@ -7089,11 +7067,6 @@ const char kShimlessRMAComplianceCheckDescription[] = "Enable device compliance check in the Shimless RMA flow"; -const char kShimlessRMASkuDescriptionName[] = - "Enable SKU description in Shimless RMA"; -const char kShimlessRMASkuDescriptionDescription[] = - "Enable device SKU description in the Shimless RMA flow"; - const char kSchedulerConfigurationName[] = "Scheduler Configuration"; const char kSchedulerConfigurationDescription[] = "Instructs the OS to use a specific scheduler configuration setting."; @@ -7598,6 +7571,11 @@ "chrome.platformKeys APIs. For instance, the new operations include sign, " "encrypt, and decrypt."; +const char kPrintPreviewCrosPrimaryName[] = + "Enables the ChromeOS print preview to be the primary print preview."; +const char kPrintPreviewCrosPrimaryDescription[] = + "Allows the ChromeOS print preview to be opened instead of the browser " + " print preview."; const char kPrintPreviewSetupAssistanceName[] = "Enable improved printer status and error messaging in Print Preview."; const char kPrintPreviewSetupAssistanceDescription[] = @@ -7849,6 +7827,30 @@ "previews."; #endif // ENABLE_PAINT_PREVIEW && BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_PDF) +const char kAccessiblePDFFormName[] = "Accessible PDF Forms"; +const char kAccessiblePDFFormDescription[] = + "Enables accessibility support for PDF forms."; + +#if BUILDFLAG(ENABLE_PDF_INK2) +const char kPdfInk2Name[] = "PDF Ink Signatures"; +const char kPdfInk2Description[] = + "Enables the ability to annotate PDFs using a new ink library."; +#endif // BUILDFLAG(ENABLE_PDF_INK2) + +const char kPdfOopifName[] = "OOPIF for PDF Viewer"; +const char kPdfOopifDescription[] = + "Use an OOPIF for the PDF Viewer, instead of a GuestView."; + +const char kPdfPortfolioName[] = "PDF portfolio"; +const char kPdfPortfolioDescription[] = "Enable PDF portfolio feature."; + +const char kPdfUseSkiaRendererName[] = "Use Skia Renderer"; +const char kPdfUseSkiaRendererDescription[] = + "Use Skia as the PDF renderer. This flag will have no effect if the " + "renderer choice is controlled by an enterprise policy."; +#endif // BUILDFLAG(ENABLE_PDF) + #if BUILDFLAG(ENABLE_VR) const char kWebXrHandInputName[] = "WebXR Hand Input"; const char kWebXrHandInputDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 01df6994..c76805bd 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -53,20 +53,6 @@ extern const char kAcceleratedVideoEncodeName[]; extern const char kAcceleratedVideoEncodeDescription[]; -#if BUILDFLAG(ENABLE_PDF) -extern const char kAccessiblePDFFormName[]; -extern const char kAccessiblePDFFormDescription[]; - -extern const char kPdfOopifName[]; -extern const char kPdfOopifDescription[]; - -extern const char kPdfPortfolioName[]; -extern const char kPdfPortfolioDescription[]; - -extern const char kPdfUseSkiaRendererName[]; -extern const char kPdfUseSkiaRendererDescription[]; -#endif - extern const char kAlignWakeUpsName[]; extern const char kAlignWakeUpsDescription[]; @@ -897,6 +883,9 @@ extern const char kBoundaryEventDispatchTracksNodeRemovalName[]; extern const char kBoundaryEventDispatchTracksNodeRemovalDescription[]; +extern const char kEnableAutomaticSharedImageManagementName[]; +extern const char kEnableAutomaticSharedImageManagementDescription[]; + extern const char kEnableCssSelectorFragmentAnchorName[]; extern const char kEnableCssSelectorFragmentAnchorDescription[]; @@ -1252,9 +1241,6 @@ extern const char kJourneysShowAllClustersName[]; extern const char kJourneysShowAllClustersDescription[]; -extern const char kJourneysIncludeSyncedVisitsName[]; -extern const char kJourneysIncludeSyncedVisitsDescription[]; - extern const char kJourneysZeroStateFilteringName[]; extern const char kJourneysZeroStateFilteringDescription[]; @@ -1264,9 +1250,6 @@ extern const char kLargeFaviconFromGoogleName[]; extern const char kLargeFaviconFromGoogleDescription[]; -extern const char kLegacyTechReportEnableCookieIssueReportsName[]; -extern const char kLegacyTechReportEnableCookieIssueReportsDescription[]; - extern const char kLegacyTechReportTopLevelUrlName[]; extern const char kLegacyTechReportTopLevelUrlDescription[]; @@ -2351,9 +2334,6 @@ extern const char kTabStateFlatBufferName[]; extern const char kTabStateFlatBufferDescription[]; -extern const char kContextMenuPopupForAllScreenSizesName[]; -extern const char kContextMenuPopupForAllScreenSizesDescription[]; - extern const char kContextualSearchSuppressShortViewName[]; extern const char kContextualSearchSuppressShortViewDescription[]; @@ -2447,9 +2427,6 @@ extern const char kInfoCardAcknowledgementTrackingName[]; extern const char kInfoCardAcknowledgementTrackingDescription[]; -extern const char kInstantStartName[]; -extern const char kInstantStartDescription[]; - extern const char kInterestFeedV2Name[]; extern const char kInterestFeedV2Description[]; @@ -2637,6 +2614,9 @@ extern const char kTabGroupSyncAndroidName[]; extern const char kTabGroupSyncAndroidDescription[]; +extern const char kTabStripGroupCollapseAndroidName[]; +extern const char kTabStripGroupCollapseAndroidDescription[]; + extern const char kTabStripGroupIndicatorsAndroidName[]; extern const char kTabStripGroupIndicatorsAndroidDescription[]; @@ -3567,6 +3547,9 @@ extern const char kQuickSettingsPWANotificationsName[]; extern const char kQuickSettingsPWANotificationsDescription[]; +extern const char kDriveFsMirroringName[]; +extern const char kDriveFsMirroringDescription[]; + extern const char kDriveFsShowCSEFilesName[]; extern const char kDriveFsShowCSEFilesDescription[]; @@ -4120,9 +4103,6 @@ extern const char kShimlessRMAComplianceCheckName[]; extern const char kShimlessRMAComplianceCheckDescription[]; -extern const char kShimlessRMASkuDescriptionName[]; -extern const char kShimlessRMASkuDescriptionDescription[]; - extern const char kShimlessRMAOsUpdateName[]; extern const char kShimlessRMAOsUpdateDescription[]; @@ -4405,6 +4385,9 @@ extern const char kPlatformKeysAesEncryptionName[]; extern const char kPlatformKeysAesEncryptionDescription[]; +extern const char kPrintPreviewCrosPrimaryName[]; +extern const char kPrintPreviewCrosPrimaryDescription[]; + extern const char kPrintPreviewSetupAssistanceName[]; extern const char kPrintPreviewSetupAssistanceDescription[]; @@ -4573,6 +4556,25 @@ extern const char kPaintPreviewDemoDescription[]; #endif // ENABLE_PAINT_PREVIEW && BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_PDF) +extern const char kAccessiblePDFFormName[]; +extern const char kAccessiblePDFFormDescription[]; + +#if BUILDFLAG(ENABLE_PDF_INK2) +extern const char kPdfInk2Name[]; +extern const char kPdfInk2Description[]; +#endif // BUILDFLAG(ENABLE_PDF_INK2) + +extern const char kPdfOopifName[]; +extern const char kPdfOopifDescription[]; + +extern const char kPdfPortfolioName[]; +extern const char kPdfPortfolioDescription[]; + +extern const char kPdfUseSkiaRendererName[]; +extern const char kPdfUseSkiaRendererDescription[]; +#endif // BUILDFLAG(ENABLE_PDF) + #if BUILDFLAG(ENABLE_VR) extern const char kWebXrInternalsName[]; extern const char kWebXrInternalsDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 617a2dd..167b4d0d 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -202,7 +202,6 @@ &kChromeSurveyNextAndroid, &kCommandLineOnNonRooted, &kContextMenuTranslateWithGoogleLens, - &kContextMenuPopupForAllScreenSizes, &kContextMenuSysUiMatchesActivity, &kContextualSearchDisableOnlineDetection, &kContextualSearchSuppressShortView, @@ -265,7 +264,6 @@ &kSuppressToolbarCaptures, &kTabDragDropAndroid, &kTabAndLinkDragDropAndroid, - &kTabStripGroupIndicatorsAndroid, &kTabGroupPaneAndroid, &kTabGroupParityAndroid, &kTabIdMapAndroid, @@ -274,6 +272,8 @@ &kTabletToolbarReordering, &kTabResumptionModuleAndroid, &kTabStateFlatBuffer, + &kTabStripGroupCollapseAndroid, + &kTabStripGroupIndicatorsAndroid, &kTabStripLayoutOptimization, &kTabStripStartupRefactoring, &kTabToGTSAnimation, @@ -574,10 +574,6 @@ "CommandLineOnNonRooted", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kContextMenuPopupForAllScreenSizes, - "ContextMenuPopupForAllScreenSizes", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kContextMenuSysUiMatchesActivity, "ContextMenuSysUiMatchesActivity", base::FEATURE_ENABLED_BY_DEFAULT); @@ -850,14 +846,6 @@ "TabIdMapAndroid", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kTabStripGroupIndicatorsAndroid, - "TabStripGroupIndicatorsAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); - -BASE_FEATURE(kTabStateFlatBuffer, - "TabStateFlatBuffer", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kTabletTabSwitcherLongPressMenu, "TabletTabSwitcherLongPressMenu", base::FEATURE_ENABLED_BY_DEFAULT); @@ -870,6 +858,18 @@ "TabletToolbarReordering", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kTabStateFlatBuffer, + "TabStateFlatBuffer", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kTabStripGroupCollapseAndroid, + "TabStripGroupCollapseAndroid", + base::FEATURE_DISABLED_BY_DEFAULT); + +BASE_FEATURE(kTabStripGroupIndicatorsAndroid, + "TabStripGroupIndicatorsAndroid", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kTabStripLayoutOptimization, "TabStripLayoutOptimization", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 9030e7ce..1f64170 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -71,7 +71,6 @@ BASE_DECLARE_FEATURE(kChromeSharingHubLaunchAdjacent); BASE_DECLARE_FEATURE(kChromeSurveyNextAndroid); BASE_DECLARE_FEATURE(kCommandLineOnNonRooted); -BASE_DECLARE_FEATURE(kContextMenuPopupForAllScreenSizes); BASE_DECLARE_FEATURE(kContextMenuSysUiMatchesActivity); BASE_DECLARE_FEATURE(kContextMenuTranslateWithGoogleLens); BASE_DECLARE_FEATURE(kContextualSearchDisableOnlineDetection); @@ -149,11 +148,12 @@ BASE_DECLARE_FEATURE(kTabGroupPaneAndroid); BASE_DECLARE_FEATURE(kTabGroupParityAndroid); BASE_DECLARE_FEATURE(kTabIdMapAndroid); -BASE_DECLARE_FEATURE(kTabStripGroupIndicatorsAndroid); -BASE_DECLARE_FEATURE(kTabStateFlatBuffer); BASE_DECLARE_FEATURE(kTabletTabSwitcherLongPressMenu); BASE_DECLARE_FEATURE(kTabletToolbarIncognitoStatus); BASE_DECLARE_FEATURE(kTabletToolbarReordering); +BASE_DECLARE_FEATURE(kTabStateFlatBuffer); +BASE_DECLARE_FEATURE(kTabStripGroupCollapseAndroid); +BASE_DECLARE_FEATURE(kTabStripGroupIndicatorsAndroid); BASE_DECLARE_FEATURE(kTabStripLayoutOptimization); BASE_DECLARE_FEATURE(kTabStripStartupRefactoring); BASE_DECLARE_FEATURE(kTabToGTSAnimation);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 90c6146..ae2ea6a 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -253,8 +253,6 @@ "ContextualSearchDisableOnlineDetection"; public static final String CONTEXTUAL_SEARCH_SUPPRESS_SHORT_VIEW = "ContextualSearchSuppressShortView"; - public static final String CONTEXT_MENU_POPUP_FOR_ALL_SCREEN_SIZES = - "ContextMenuPopupForAllScreenSizes"; public static final String CONTEXT_MENU_SYS_UI_MATCHES_ACTIVITY = "ContextMenuSysUiMatchesActivity"; public static final String CONTEXT_MENU_TRANSLATE_WITH_GOOGLE_LENS = @@ -457,6 +455,7 @@ public static final String TAB_LINK_DRAG_DROP_ANDROID = "TabAndLinkDragDropAndroid"; public static final String TAB_RESUMPTION_MODULE_ANDROID = "TabResumptionModuleAndroid"; public static final String TAB_ID_MAP = "TabIdMapAndroid"; + public static final String TAB_STRIP_GROUP_COLLAPSE = "TabStripGroupCollapseAndroid"; public static final String TAB_STRIP_GROUP_INDICATORS = "TabStripGroupIndicatorsAndroid"; public static final String TAB_STRIP_LAYOUT_OPTIMIZATION = "TabStripLayoutOptimization"; public static final String TAB_STRIP_STARTUP_REFACTORING = "TabStripStartupRefactoring"; @@ -649,6 +648,8 @@ newCachedFlag(TABLET_TOOLBAR_INCOGNITO_STATUS, true); public static final CachedFlag sTabletToolbarReordering = newCachedFlag(TABLET_TOOLBAR_REORDERING, false); + public static final CachedFlag sTabStripGroupCollapse = + newCachedFlag(TAB_STRIP_GROUP_COLLAPSE, false); public static final CachedFlag sTabStripGroupIndicators = newCachedFlag(TAB_STRIP_GROUP_INDICATORS, false); public static final CachedFlag sTabToGTSAnimation = newCachedFlag(TAB_TO_GTS_ANIMATION, true); @@ -745,6 +746,7 @@ sTabLinkDragDropAndroid, sTabResumptionModuleAndroid, sTabStateFlatBuffer, + sTabStripGroupCollapse, sTabStripGroupIndicators, sTabStripLayoutOptimization, sTabStripStartupRefactoring,
diff --git a/chrome/browser/flags/android/java_templates/ChromeSwitches.java.tmpl b/chrome/browser/flags/android/java_templates/ChromeSwitches.java.tmpl index d66ae094..bbc9fed 100644 --- a/chrome/browser/flags/android/java_templates/ChromeSwitches.java.tmpl +++ b/chrome/browser/flags/android/java_templates/ChromeSwitches.java.tmpl
@@ -80,6 +80,11 @@ */ public static final String DISABLE_NATIVE_INITIALIZATION = "disable-native-initialization"; + /** + * Force enable the popup context menu to unblock drag and drop from web contents on phones. + */ + public static final String FORCE_CONTEXT_MENU_POPUP = "force-context-menu-popup"; + /////////////////////////////////////////////////////////////////////////////////////////////// // Native Switches ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc b/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc index 84a3396..de5f202 100644 --- a/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc +++ b/chrome/browser/history_embeddings/history_embeddings_service_browsertest.cc
@@ -121,7 +121,7 @@ // Search for the passage. base::test::TestFuture<SearchResult> search_future; - service()->Search("A B C D e f g", 1, search_future.GetCallback()); + service()->Search("A B C D e f g", {}, 1, search_future.GetCallback()); SearchResult result = search_future.Take(); EXPECT_EQ(result.size(), 1u); EXPECT_EQ(result[0].scored_url.passage, "A B C D"); @@ -154,7 +154,7 @@ // Search for the passage. base::test::TestFuture<SearchResult> search_future; - service()->Search("A B C D e f g", 1, search_future.GetCallback()); + service()->Search("A B C D e f g", {}, 1, search_future.GetCallback()); SearchResult result = search_future.Take(); EXPECT_TRUE(result.empty()); @@ -182,7 +182,7 @@ // Search for the passage. base::test::TestFuture<SearchResult> search_future; - service()->Search("A B C D e f g", 1, search_future.GetCallback()); + service()->Search("A B C D e f g", {}, 1, search_future.GetCallback()); SearchResult result = search_future.Take(); EXPECT_TRUE(result.empty());
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubContainerView.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubContainerView.java index 0236b5f..b705fe8f 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubContainerView.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubContainerView.java
@@ -7,8 +7,11 @@ import android.content.Context; import android.widget.FrameLayout; +import org.chromium.base.Log; + /** Container view for the Hub. */ public class HubContainerView extends FrameLayout implements RunOnNextLayout { + private static final String TAG = "HubContainerView"; private final RunOnNextLayoutDelegate mRunOnNextLayoutDelegate; /** Default {@link FrameLayout} constructor. */ @@ -32,4 +35,11 @@ public void runOnNextLayoutRunnables() { mRunOnNextLayoutDelegate.runOnNextLayoutRunnables(); } + + @Override + public void setY(float y) { + super.setY(y); + Log.i(TAG, "Setting HubContainerView y-offset to " + y); + Thread.dumpStack(); + } }
diff --git a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubManager.java b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubManager.java index 04199ce..0e698d9 100644 --- a/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubManager.java +++ b/chrome/browser/hub/android/java/src/org/chromium/chrome/browser/hub/HubManager.java
@@ -33,4 +33,7 @@ /** Sets the status indicator height. */ void setStatusIndicatorHeight(int height); + + /** Sets the app header height. */ + void setAppHeaderHeight(int height); }
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java index f914988..43fb66b 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImpl.java
@@ -49,6 +49,9 @@ private HubCoordinator mHubCoordinator; + private int mStatusIndicatorHeight; + private int mAppHeaderHeight; + /** See {@link HubManagerFactory#createHubManager}. */ public HubManagerImpl( @NonNull Context context, @@ -101,7 +104,18 @@ public void setStatusIndicatorHeight(int height) { LayoutParams params = (LayoutParams) mHubContainerView.getLayoutParams(); assert params != null : "HubContainerView should always have layout params."; - params.topMargin = height; + mStatusIndicatorHeight = height; + params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight; + mHubContainerView.setLayoutParams(params); + } + + @Override + public void setAppHeaderHeight(int height) { + if (mAppHeaderHeight == height) return; + LayoutParams params = (LayoutParams) mHubContainerView.getLayoutParams(); + assert params != null : "HubContainerView should always have layout params."; + mAppHeaderHeight = height; + params.topMargin = mStatusIndicatorHeight + mAppHeaderHeight; mHubContainerView.setLayoutParams(params); }
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java index 32363f3..755e5c5a 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/HubManagerImplUnitTest.java
@@ -279,4 +279,46 @@ assertEquals( statusIndicatorHeight, ((LayoutParams) containerView.getLayoutParams()).topMargin); } + + @Test + @SmallTest + public void testAppHeaderHeight() { + PaneListBuilder builder = + new PaneListBuilder(new DefaultPaneOrderController()) + .registerPane( + PaneId.TAB_SWITCHER, + LazyOneshotSupplier.fromValue(mTabSwitcherPane)) + .registerPane( + PaneId.INCOGNITO_TAB_SWITCHER, + LazyOneshotSupplier.fromValue(mIncognitoTabSwitcherPane)); + HubManagerImpl hubManager = + new HubManagerImpl( + mActivity, + builder, + mBackPressManager, + mMenuOrKeyboardActionController, + mSnackbarManager, + mTabSupplier, + mMenuButtonCoordinator); + hubManager.getPaneManager().focusPane(PaneId.TAB_SWITCHER); + + HubController hubController = hubManager.getHubController(); + hubController.setHubLayoutController(mHubLayoutController); + hubController.onHubLayoutShow(); + + int appHeaderHeight = 75; + hubManager.setAppHeaderHeight(appHeaderHeight); + FrameLayout containerView = hubController.getContainerView(); + assertEquals(appHeaderHeight, ((LayoutParams) containerView.getLayoutParams()).topMargin); + + mRootView.addView(containerView); + assertEquals(appHeaderHeight, ((LayoutParams) containerView.getLayoutParams()).topMargin); + + appHeaderHeight = 0; + hubManager.setAppHeaderHeight(appHeaderHeight); + assertEquals(appHeaderHeight, ((LayoutParams) containerView.getLayoutParams()).topMargin); + + mRootView.removeView(containerView); + assertEquals(appHeaderHeight, ((LayoutParams) containerView.getLayoutParams()).topMargin); + } }
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactory.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactory.java index 8a0fec0..e698485 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactory.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactory.java
@@ -15,32 +15,36 @@ /** * Creates a {@link HubLayoutAnimatorProvider} for translating up to show. * - * @param hubLayoutContainerView The {@link HubContainerView} to animate. + * @param hubContainerView The {@link HubContainerView} to animate. * @param scrimController A controller to manage showing a scrim. * @param durationMs The duration in milliseconds of the animation. + * @param yOffset The y-offset for the container view, in px. * @return a {@link HubLayoutAnimatorProvider} that provides the animation. */ public static HubLayoutAnimatorProvider createTranslateUpAnimatorProvider( @NonNull HubContainerView hubContainerView, @NonNull ScrimController scrimController, - long durationMs) { + long durationMs, + float yOffset) { return TranslateHubLayoutAnimationFactoryImpl.createTranslateUpAnimatorProvider( - hubContainerView, scrimController, durationMs); + hubContainerView, scrimController, durationMs, yOffset); } /** * Creates a {@link HubLayoutAnimatorProvider} for translating down to hide. * - * @param hubLayoutContainerView The {@link HubContainerView} to animate. + * @param hubContainerView The {@link HubContainerView} to animate. * @param scrimController A controller to manage hiding a scrim. * @param durationMs The duration in milliseconds of the animation. + * @param yOffset The y-offset for the container view, in px. * @return a {@link HubLayoutAnimatorProvider} that provides the animation. */ public static HubLayoutAnimatorProvider createTranslateDownAnimatorProvider( @NonNull HubContainerView hubContainerView, @NonNull ScrimController scrimController, - long durationMs) { + long durationMs, + float yOffset) { return TranslateHubLayoutAnimationFactoryImpl.createTranslateDownAnimatorProvider( - hubContainerView, scrimController, durationMs); + hubContainerView, scrimController, durationMs, yOffset); } }
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImpl.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImpl.java index 4f71ad0..ee48c9c 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImpl.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImpl.java
@@ -23,7 +23,8 @@ public static HubLayoutAnimatorProvider createTranslateUpAnimatorProvider( @NonNull HubContainerView hubContainerView, @NonNull ScrimController scrimController, - long durationMs) { + long durationMs, + float yOffset) { AnimatorSet animatorSet = new AnimatorSet(); HubLayoutAnimationListener listener = @@ -41,7 +42,7 @@ hubContainerView, View.TRANSLATION_Y, hubContainerView.getHeight(), - 0f); + yOffset); animator.setInterpolator(Interpolators.EMPHASIZED_DECELERATE); animator.setDuration(durationMs); animatorSet.play(animator); @@ -52,7 +53,7 @@ @Override public void afterEnd() { // Carried over from the legacy implementation in TabSwitcherLayout. - hubContainerView.setY(0f); + hubContainerView.setY(yOffset); } }; @@ -68,10 +69,14 @@ public static HubLayoutAnimatorProvider createTranslateDownAnimatorProvider( @NonNull HubContainerView hubContainerView, @NonNull ScrimController scrimController, - long durationMs) { + long durationMs, + float yOffset) { ObjectAnimator animator = ObjectAnimator.ofFloat( - hubContainerView, View.TRANSLATION_Y, 0f, hubContainerView.getHeight()); + hubContainerView, + View.TRANSLATION_Y, + yOffset, + hubContainerView.getHeight()); animator.setInterpolator(Interpolators.EMPHASIZED_ACCELERATE); animator.setDuration(durationMs); @@ -88,7 +93,7 @@ @Override public void afterEnd() { // Reset the Y offset for the next animation. - hubContainerView.setY(0f); + hubContainerView.setY(yOffset); } }; return new PresetHubLayoutAnimatorProvider(
diff --git a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImplUnitTest.java b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImplUnitTest.java index a0e4cd2..b8703f05 100644 --- a/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImplUnitTest.java +++ b/chrome/browser/hub/internal/android/java/src/org/chromium/chrome/browser/hub/TranslateHubLayoutAnimationFactoryImplUnitTest.java
@@ -76,7 +76,7 @@ public void testTranslateUp() { HubLayoutAnimatorProvider animatorProvider = TranslateHubLayoutAnimationFactory.createTranslateUpAnimatorProvider( - mHubContainerView, mScrimController, DURATION_MS); + mHubContainerView, mScrimController, DURATION_MS, 50); assertEquals( HubLayoutAnimationType.TRANSLATE_UP, animatorProvider.getPlannedAnimationType()); @@ -99,7 +99,7 @@ @Override public void onEnd(boolean wasForcedToFinish) { assertEquals(View.VISIBLE, mHubContainerView.getVisibility()); - assertEquals(0.0f, mHubContainerView.getY(), FLOAT_TOLERANCE); + assertEquals(50f, mHubContainerView.getY(), FLOAT_TOLERANCE); } }); runner.addListener(mListener); @@ -122,7 +122,7 @@ HubLayoutAnimatorProvider animatorProvider = TranslateHubLayoutAnimationFactory.createTranslateDownAnimatorProvider( - mHubContainerView, mScrimController, DURATION_MS); + mHubContainerView, mScrimController, DURATION_MS, 50); assertEquals( HubLayoutAnimationType.TRANSLATE_DOWN, animatorProvider.getPlannedAnimationType()); @@ -148,7 +148,7 @@ @Override public void afterEnd() { - assertEquals(0.0f, mHubContainerView.getY(), FLOAT_TOLERANCE); + assertEquals(50f, mHubContainerView.getY(), FLOAT_TOLERANCE); } }); runner.addListener(mListener);
diff --git a/chrome/browser/lens/lens_overlay/lens_overlay_image_helper.cc b/chrome/browser/lens/lens_overlay/lens_overlay_image_helper.cc index f126d8a..65a2940 100644 --- a/chrome/browser/lens/lens_overlay/lens_overlay_image_helper.cc +++ b/chrome/browser/lens/lens_overlay/lens_overlay_image_helper.cc
@@ -94,7 +94,8 @@ int compression_quality, scoped_refptr<base::RefCountedBytes>* output) { *output = base::MakeRefCounted<base::RefCountedBytes>(); - return gfx::JPEGCodec::Encode(image, compression_quality, &(*output)->data()); + return gfx::JPEGCodec::Encode(image, compression_quality, + &(*output)->as_vector()); } lens::ImageData DownscaleAndEncodeBitmap(const SkBitmap& image) {
diff --git a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.cc b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.cc index 1caaf1a8..0d76a96 100644 --- a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.cc +++ b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.cc
@@ -111,10 +111,12 @@ LensOverlayFullImageResponseCallback full_image_callback, LensOverlayUrlResponseCallback url_callback, LensOverlayInteractionResponseCallback interaction_data_callback, + LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager) : full_image_callback_(std::move(full_image_callback)), interaction_data_callback_(std::move(interaction_data_callback)), + thumbnail_created_callback_(std::move(thumbnail_created_callback)), request_id_generator_( std::make_unique<lens::LensOverlayRequestIdGenerator>()), url_callback_(std::move(url_callback)), @@ -313,6 +315,10 @@ FetchInteractionRequestAndGenerateLensSearchUrl, weak_ptr_factory_.GetWeakPtr(), request_index, std::move(region), query_text, object_id, additional_search_query_params, image_crop); + + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(thumbnail_created_callback_, + image_crop->image().image_content())); } lens::LensOverlayServerRequest
diff --git a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.h b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.h index 9788a8b..44ded3a 100644 --- a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.h +++ b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller.h
@@ -41,6 +41,9 @@ // Callback type alias for the lens overlay interaction data response. using LensOverlayInteractionResponseCallback = base::RepeatingCallback<void(lens::proto::LensOverlayInteractionResponse)>; +// Callback type alias for the thumbnail image creation. +using LensOverlayThumbnailCreatedCallback = + base::RepeatingCallback<void(const std::string&)>; // Manages queries on behalf of a Lens overlay. class LensOverlayQueryController { public: @@ -48,6 +51,7 @@ LensOverlayFullImageResponseCallback full_image_callback, LensOverlayUrlResponseCallback url_callback, LensOverlayInteractionResponseCallback interaction_data_callback, + LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager); virtual ~LensOverlayQueryController(); @@ -97,6 +101,9 @@ // Interaction data callback for an interaction. LensOverlayInteractionResponseCallback interaction_data_callback_; + // Callback for when a thumbnail image is created from a region selection. + LensOverlayThumbnailCreatedCallback thumbnail_created_callback_; + private: enum class QueryControllerState { // StartQueryFlow has not been called and the query controller is inactive. @@ -141,6 +148,8 @@ // Helper to gate interaction fetches on whether or not the cluster // info has been received. If it has not been received, this function // sets the cluster info received callback to fetch the interaction. + // Additionally, invokes `thumbnail_created_callback_` and passes the data in + // `image_crop`. void FetchInteractionRequestAndGenerateUrlIfClusterInfoReady( int request_index, lens::mojom::CenterRotatedBoxPtr region,
diff --git a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller_unittest.cc b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller_unittest.cc index a83196712..c515cac 100644 --- a/chrome/browser/lens/lens_overlay/lens_overlay_query_controller_unittest.cc +++ b/chrome/browser/lens/lens_overlay/lens_overlay_query_controller_unittest.cc
@@ -64,11 +64,14 @@ url_callback, base::RepeatingCallback<void(lens::proto::LensOverlayInteractionResponse)> interaction_data_callback, + base::RepeatingCallback<void(const std::string&)> + thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager) : LensOverlayQueryController(full_image_callback, url_callback, interaction_data_callback, + thumbnail_created_callback, variations_client, identity_manager) {} ~LensOverlayQueryControllerMock() override = default; @@ -139,7 +142,8 @@ full_image_response_future; LensOverlayQueryControllerMock query_controller( full_image_response_future.GetRepeatingCallback(), base::NullCallback(), - base::NullCallback(), profile()->GetVariationsClient(), + base::NullCallback(), base::NullCallback(), + profile()->GetVariationsClient(), IdentityManagerFactory::GetForProfile(profile())); SkBitmap bitmap = CreateNonEmptyBitmap(100, 100); query_controller.StartQueryFlow(bitmap); @@ -171,10 +175,12 @@ url_response_future; base::test::TestFuture<lens::proto::LensOverlayInteractionResponse> interaction_data_response_future; + base::test::TestFuture<const std::string&> thumbnail_created_future; LensOverlayQueryControllerMock query_controller( full_image_response_future.GetRepeatingCallback(), url_response_future.GetRepeatingCallback(), interaction_data_response_future.GetRepeatingCallback(), + thumbnail_created_future.GetRepeatingCallback(), profile()->GetVariationsClient(), IdentityManagerFactory::GetForProfile(profile())); query_controller.fake_objects_response_.mutable_cluster_info() @@ -258,10 +264,12 @@ url_response_future; base::test::TestFuture<lens::proto::LensOverlayInteractionResponse> interaction_data_response_future; + base::test::TestFuture<const std::string&> thumbnail_created_future; LensOverlayQueryControllerMock query_controller( full_image_response_future.GetRepeatingCallback(), url_response_future.GetRepeatingCallback(), interaction_data_response_future.GetRepeatingCallback(), + thumbnail_created_future.GetRepeatingCallback(), profile()->GetVariationsClient(), IdentityManagerFactory::GetForProfile(profile())); query_controller.fake_objects_response_.mutable_cluster_info() @@ -348,10 +356,12 @@ url_response_future; base::test::TestFuture<lens::proto::LensOverlayInteractionResponse> interaction_data_response_future; + base::test::TestFuture<const std::string&> thumbnail_created_future; LensOverlayQueryControllerMock query_controller( full_image_response_future.GetRepeatingCallback(), url_response_future.GetRepeatingCallback(), interaction_data_response_future.GetRepeatingCallback(), + thumbnail_created_future.GetRepeatingCallback(), profile()->GetVariationsClient(), IdentityManagerFactory::GetForProfile(profile())); query_controller.fake_objects_response_.mutable_cluster_info() @@ -417,10 +427,12 @@ url_response_future; base::test::TestFuture<lens::proto::LensOverlayInteractionResponse> interaction_data_response_future; + base::test::TestFuture<const std::string&> thumbnail_created_future; LensOverlayQueryControllerMock query_controller( full_image_response_future.GetRepeatingCallback(), url_response_future.GetRepeatingCallback(), interaction_data_response_future.GetRepeatingCallback(), + thumbnail_created_future.GetRepeatingCallback(), profile()->GetVariationsClient(), IdentityManagerFactory::GetForProfile(profile())); SkBitmap bitmap = CreateNonEmptyBitmap(100, 100);
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index ed7f2f4..45617b63 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -174,6 +174,7 @@ #include "chrome/browser/metrics/family_user_metrics_provider.h" #include "chrome/browser/metrics/per_user_state_manager_chromeos.h" #include "chrome/browser/metrics/update_engine_metrics_provider.h" +#include "chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.h" #include "chrome/browser/ui/webui/ash/settings/services/metrics/os_settings_metrics_provider.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -959,6 +960,9 @@ std::make_unique<ChromeOSFamilyLinkUserMetricsProvider>()); metrics_service_->RegisterMetricsProvider( + std::make_unique<ChromeShelfMetricsProvider>()); + + metrics_service_->RegisterMetricsProvider( std::make_unique<UpdateEngineMetricsProvider>()); if (base::FeatureList::IsEnabled(
diff --git a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc index 05f84d3..0de0ec7 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
@@ -242,14 +242,14 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // AmbientModeMetricsProvider, AssistantServiceMetricsProvider, // CrosHealthdMetricsProvider, ChromeOSMetricsProvider, - // ChromeOSHistogramMetricsProvider, + // ChromeOSHistogramMetricsProvider, ChromeShelfMetricsProvider, // KeyboardBacklightColorMetricsProvider, // PersonalizationAppThemeMetricsProvider, PrinterMetricsProvider, // FamilyUserMetricsProvider, FamilyLinkUserMetricsProvider, // UpdateEngineMetricsProvider, OsSettingsMetricsProvider, // UserTypeByDeviceTypeMetricsProvider, WallpaperMetricsProvider, // and VmmMetricsProvider. - expected_providers += 15; + expected_providers += 16; #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc index ccdc0a2..842eb19 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_factory.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chrome/browser/nearby_sharing/nearby_sharing_service_impl.h" #include "chrome/browser/nearby_sharing/power_client_chromeos.h" #include "chrome/browser/nearby_sharing/wifi_network_configuration/wifi_network_configuration_handler.h" @@ -24,6 +23,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "components/cross_device/logging/logging.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/net/cert_verifier_service_browsertest.cc b/chrome/browser/net/cert_verifier_service_browsertest.cc index 666f6a60..e864eaa 100644 --- a/chrome/browser/net/cert_verifier_service_browsertest.cc +++ b/chrome/browser/net/cert_verifier_service_browsertest.cc
@@ -20,6 +20,7 @@ #include "net/cert/internal/trust_store_chrome.h" #include "net/cert/internal/trust_store_features.h" #include "net/cert/x509_util.h" +#include "net/dns/mock_host_resolver.h" #include "net/net_buildflags.h" #include "net/test/cert_test_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -44,6 +45,8 @@ SystemNetworkContextManager::SetEnableCertificateTransparencyForTesting( false); + host_resolver()->AddRule("*", "127.0.0.1"); + content::GetCertVerifierServiceFactory()->SetUseChromeRootStore( use_chrome_root_store(), base::DoNothing()); } @@ -69,9 +72,10 @@ net::EmbeddedTestServer::TYPE_HTTPS); // Use a runtime generated cert, as the pre-generated ok_cert has too long of // a validity period to be accepted by a publicly trusted root. - https_test_server.SetSSLConfig( - net::test_server::EmbeddedTestServer::CERT_AUTO); https_test_server.ServeFilesFromSourceDirectory("chrome/test/data"); + // The test uses a certificate with a publicly resolvable name, since Chrome + // rejects certificates for non-unique names from publicly trusted CAs. + https_test_server.SetCertHostnames({"example.com"}); ASSERT_TRUE(https_test_server.Start()); // Clear test roots so that cert validation only happens with @@ -97,8 +101,9 @@ } EXPECT_EQ(use_chrome_root_store(), - content::NavigateToURL(GetActiveWebContents(), - https_test_server.GetURL("/simple.html"))); + content::NavigateToURL( + GetActiveWebContents(), + https_test_server.GetURL("example.com", "/simple.html"))); // The navigation should show an interstitial if CRS was not in use, since // the root was only trusted in the test CRS update and won't be trusted by
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h index b52ac8ea1..4776f1b 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -180,7 +180,7 @@ } optimization_guide::ChromeModelQualityLogsUploaderService* - GetChromeModelQualityLogsUploaderServiceForTesting() { + GetChromeModelQualityLogsUploaderService() { return model_quality_logs_uploader_service_.get(); }
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc index ef1c3b7..65c6688 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
@@ -359,9 +359,7 @@ return std::make_unique<optimization_guide::ModelQualityLogEntry>( std::move(log_ai_data_request), - ogks() - ->GetChromeModelQualityLogsUploaderServiceForTesting() - ->GetWeakPtr()); + ogks()->GetChromeModelQualityLogsUploaderService()->GetWeakPtr()); } GURL url_with_hints() { return url_with_hints_; } @@ -1441,7 +1439,7 @@ g_browser_process->GetMetricsServicesManager()->IsMetricsConsentGiven()); EXPECT_FALSE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Upload should be disabled as there is no metrics consent, so total @@ -1568,7 +1566,7 @@ EXPECT_TRUE(ogks->ShouldFeatureBeCurrentlyAllowedForLogging(compose_feature)); EXPECT_TRUE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Create a new ModelQualityLogEntry and pass it to the @@ -1622,7 +1620,7 @@ ogks->ShouldFeatureBeCurrentlyAllowedForLogging(compose_feature)); EXPECT_FALSE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Disable logging via via the enterprise policy to kDisable state this should @@ -1641,7 +1639,7 @@ ogks->ShouldFeatureBeCurrentlyAllowedForLogging(compose_feature)); EXPECT_FALSE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Enable logging via via the enterprise policy to state kAllow this shouldn't @@ -1663,7 +1661,7 @@ EXPECT_TRUE(ogks->ShouldFeatureBeCurrentlyAllowedForLogging(compose_feature)); EXPECT_TRUE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Upload should be disabled twice when logging is disabled via enterprise @@ -1707,7 +1705,7 @@ EXPECT_TRUE(ogks->ShouldFeatureBeCurrentlyAllowedForLogging(compose_feature)); EXPECT_TRUE( - ogks->GetChromeModelQualityLogsUploaderServiceForTesting()->CanUploadLogs( + ogks->GetChromeModelQualityLogsUploaderService()->CanUploadLogs( optimization_guide::UserVisibleFeatureKey::kCompose)); // Create a new ModelQualityLogEntry for compose.
diff --git a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc index 5ebf17f3..17caa1c6 100644 --- a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc
@@ -317,9 +317,7 @@ internal::LCPPPredictResult result; const int max_lcpp_histogram_buckets = - base::GetFieldTrialParamByFeatureAsInt( - features::kLoadingPredictorTableConfig, "max_lcpp_histogram_buckets", - 10) + + blink::features::kLCPCriticalPathPredictorMaxHistogramBuckets.Get() + internal::kLCPIndexHistogramOffset; if (first_valid_index_except_last) { if (last_lcp_index) {
diff --git a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer_unittest.cc index ca671c58..5e71522f 100644 --- a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer_unittest.cc
@@ -82,9 +82,8 @@ loading_predictor->resource_prefetch_predictor()); initializer.WaitUntilInitialized(); - max_lcpp_histogram_buckets_ = base::GetFieldTrialParamByFeatureAsInt( - features::kLoadingPredictorTableConfig, "max_lcpp_histogram_buckets", - 10); + max_lcpp_histogram_buckets_ = + blink::features::kLCPCriticalPathPredictorMaxHistogramBuckets.Get(); } void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index 476654dd..ead3f4a 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -150,8 +150,8 @@ FormFieldData field; field.set_name(u"password-element"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(FieldRendererId(123)); form_data.fields.push_back(field);
diff --git a/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc b/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc index 1d0ff9f..eadf0b7 100644 --- a/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc +++ b/chrome/browser/picture_in_picture/auto_picture_in_picture_tab_helper_browsertest.cc
@@ -545,18 +545,9 @@ /*should_document_pip=*/false); } -// TODO(crbug.com/40923043): Flaky on "Linux ASan LSan Tests (1)" and "Linux -// Chromium OS ASan LSan Tests (1)" -#if (BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) || \ - BUILDFLAG(IS_LINUX)) && \ - defined(ADDRESS_SANITIZER) && defined(LEAK_SANITIZER) -#define MAYBE_OpensAndClosesDocumentAutopip \ - DISABLED_OpensAndClosesDocumentAutopip -#else -#define MAYBE_OpensAndClosesDocumentAutopip OpensAndClosesDocumentAutopip -#endif +// TODO(crbug.com/335630150): Flaky. IN_PROC_BROWSER_TEST_F(AutoPictureInPictureWithVideoPlaybackBrowserTest, - MAYBE_OpensAndClosesDocumentAutopip) { + DISABLED_OpensAndClosesDocumentAutopip) { // Load a page that registers for autopip and start video playback. LoadAutoDocumentPipPage(browser()); auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc index ce1b78d..5eddd8c 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc
@@ -122,7 +122,8 @@ // // Instantiate. // LcppFrequencyStatDataUpdater updater = // LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( -// config, *data.mutable_lcpp_stat()->mutable_lcp_script_url_stat()); +// sliding_window_size, max_histogram_buckets, +// *data.mutable_lcpp_stat()->mutable_lcp_script_url_stat()); // // Update. // updater.Update(url); // // Extract. @@ -203,14 +204,15 @@ static std::unique_ptr<LcppFrequencyStatDataUpdater> FromLcppStringFrequencyStatData( - const LoadingPredictorConfig& config, + size_t sliding_window_size, + size_t max_histogram_buckets, const LcppStringFrequencyStatData& lcpp_stat_data) { // Prepare working variables (histogram and other_bucket_frequency) from // proto. If the data is corrupted, the previous data will be cleared. bool corrupted = false; double other_bucket_frequency = lcpp_stat_data.other_bucket_frequency(); - if (other_bucket_frequency < 0 || lcpp_stat_data.main_buckets().size() > - config.max_lcpp_histogram_buckets) { + if (other_bucket_frequency < 0 || + lcpp_stat_data.main_buckets().size() > max_histogram_buckets) { corrupted = true; } std::map<std::string, double> histogram; @@ -226,7 +228,8 @@ histogram.clear(); } return base::WrapUnique(new LcppFrequencyStatDataUpdater( - config, histogram, other_bucket_frequency)); + sliding_window_size, max_histogram_buckets, histogram, + other_bucket_frequency)); } static std::unique_ptr<LcppFrequencyStatDataUpdater> @@ -258,7 +261,8 @@ histogram.clear(); } return base::WrapUnique(new LcppFrequencyStatDataUpdater( - config, histogram, other_bucket_frequency)); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, histogram, other_bucket_frequency)); } void Update(const std::string& new_entry) { @@ -341,11 +345,12 @@ size_t num_matched() const { return num_matched_; } private: - LcppFrequencyStatDataUpdater(const LoadingPredictorConfig& config, + LcppFrequencyStatDataUpdater(size_t sliding_window_size, + size_t max_histogram_buckets, std::map<std::string, double> histogram, double other_bucket_frequency) - : sliding_window_size_(config.lcpp_histogram_sliding_window_size), - max_histogram_buckets_(config.max_lcpp_histogram_buckets), + : sliding_window_size_(sliding_window_size), + max_histogram_buckets_(max_histogram_buckets), histogram_(histogram), other_bucket_frequency_(other_bucket_frequency) {} @@ -383,7 +388,9 @@ // for an origin. Record each in a separate histogram. std::unique_ptr<LcppFrequencyStatDataUpdater> updater = LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( - config, data.mutable_lcpp_stat()->lcp_script_url_stat()); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, + data.mutable_lcpp_stat()->lcp_script_url_stat()); CHECK(updater); for (auto& script_url : lcp_influencer_scripts) { const auto& lcpp_script = script_url.spec(); @@ -404,7 +411,9 @@ // histogram. std::unique_ptr<LcppFrequencyStatDataUpdater> updater = LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( - config, data.mutable_lcpp_stat()->preconnect_origin_stat()); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, + data.mutable_lcpp_stat()->preconnect_origin_stat()); CHECK(updater); for (auto& origin : origins) { const auto& origin_spec = origin.spec(); @@ -426,7 +435,9 @@ // a static data. std::unique_ptr<LcppFrequencyStatDataUpdater> updater = LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( - config, data.mutable_lcpp_stat()->fetched_font_url_stat()); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, + data.mutable_lcpp_stat()->fetched_font_url_stat()); std::set<GURL> used_urls; size_t max_url_length = 0; for (const auto& url : fetched_font_urls) { @@ -485,7 +496,9 @@ std::unique_ptr<LcppFrequencyStatDataUpdater> updater = LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( - config, data.mutable_lcpp_stat()->fetched_subresource_url_stat()); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, + data.mutable_lcpp_stat()->fetched_subresource_url_stat()); for (const auto& [resource_load_start, subresource_url] : time_and_urls) { if (!IsValidUrlInLcppStringFrequencyStatData(subresource_url)) { continue; @@ -517,7 +530,9 @@ LcppData& data) { std::unique_ptr<LcppFrequencyStatDataUpdater> updater = LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( - config, data.mutable_lcpp_stat()->unused_preload_stat()); + config.lcpp_histogram_sliding_window_size, + config.max_lcpp_histogram_buckets, + data.mutable_lcpp_stat()->unused_preload_stat()); CHECK(updater); for (auto& url : unused_preloads) { if (!IsValidUrlInLcppStringFrequencyStatData(url.spec())) { @@ -753,6 +768,18 @@ return data_updated; } +void UpdateLcppStringFrequencyStatData( + size_t sliding_window_size, + size_t max_histogram_buckets, + const std::string& new_entry, + LcppStringFrequencyStatData& lcpp_stat_data) { + std::unique_ptr<LcppFrequencyStatDataUpdater> updater = + LcppFrequencyStatDataUpdater::FromLcppStringFrequencyStatData( + sliding_window_size, max_histogram_buckets, lcpp_stat_data); + updater->Update(new_entry); + lcpp_stat_data = updater->ToLcppStringFrequencyStatData(); +} + bool IsValidLcppStat(const LcppStat& lcpp_stat) { if (lcpp_stat.has_lcp_element_locator_stat() && !IsValidLcpElementLocatorHistogram( @@ -788,16 +815,12 @@ url.host().size() <= ResourcePrefetchPredictorTables::kMaxStringLength; } -std::string GetLCPPDatabaseKey(const GURL& url) { +std::string GetFirstLevelPath(const GURL& url) { CHECK(IsURLValidForLcpp(url)); - if (!base::FeatureList::IsEnabled(blink::features::kLCPPMultipleKey)) { - return url.host(); - } - const std::string path = url.path(); if (path.length() < 2) { // path == "/" - return url.host(); + return std::string(); } // Say path is "/foo/baz", find second '/' to cut out the first level path // "/foo". @@ -814,20 +837,13 @@ path_view.length() == max_path_length + 1) { // Assume having a file extension is a file and // path should not be a file name nor exceed the length limit - return url.host(); + return std::string(); } first_level_path_length = path_view.length(); } else { first_level_path_length = second_slash_pos; } - const size_t key_length = url.host().length() + first_level_path_length; - if (key_length > ResourcePrefetchPredictorTables::kMaxStringLength) { - // The key must not be longer than `kMaxStringLength`. - // Note that we confirmed that url.host() is less than the limit in - // `IsURLValidForLcpp()`. - return url.host(); - } - return url.host() + url.path().substr(0, first_level_path_length); + return url.path().substr(0, first_level_path_length); } } // namespace predictors
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h index ab743b71..b8a0c013 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h
@@ -89,6 +89,12 @@ const LcppDataInputs& inputs, LcppData& data); +void UpdateLcppStringFrequencyStatData( + size_t sliding_window_size, + size_t max_histogram_buckets, + const std::string& new_entry, + LcppStringFrequencyStatData& lcpp_stat_data); + // Returns true if the LcppData is valid. i.e. looks not corrupted. // Otherwise, data might be corrupted. bool IsValidLcppStat(const LcppStat& lcpp_stat); @@ -96,9 +102,11 @@ // Returns true if the url is valid for learning. bool IsURLValidForLcpp(const GURL& url); -// Returns the key string for the url. The url should be true for +// Returns the first level path of the url. The url should be true for // the above IsURLValidForLcpp(url). -std::string GetLCPPDatabaseKey(const GURL& url); +// This function can return empty string if the URL doesn't have +// the first level path or it length exceeds kLCPPMultipleKeyMaxPathLength. +std::string GetFirstLevelPath(const GURL& url); } // namespace predictors
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc index 4caa59af..16b0ec7 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util_unittest.cc
@@ -5,11 +5,82 @@ #include "chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/predictors/loading_test_util.h" #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" namespace predictors { +namespace { +class Updater { + public: + Updater(size_t sliding_window_size, size_t max_histogram_buckets) + : sliding_window_size_(sliding_window_size), + max_histogram_buckets_(max_histogram_buckets) {} + ~Updater() = default; + + void Update(const std::string& new_entry) { + UpdateLcppStringFrequencyStatData( + sliding_window_size_, max_histogram_buckets_, new_entry, stat_data_); + } + + const LcppStringFrequencyStatData& Data() { return stat_data_; } + + private: + LcppStringFrequencyStatData stat_data_; + const size_t sliding_window_size_; + const size_t max_histogram_buckets_; +}; + +LcppStringFrequencyStatData MakeData(std::map<std::string, double> main_buckets, + double others) { + LcppStringFrequencyStatData data; + for (auto& [key, freq] : main_buckets) { + data.mutable_main_buckets()->insert({key, freq}); + } + data.set_other_bucket_frequency(others); + return data; +} + +} // namespace + +TEST(UpdateLcppStringFrequencyStatDataTest, Base) { + Updater updater(/*sliding_window_size=*/5u, + /*max_histogram_buckets=*/2u); + EXPECT_EQ(updater.Data(), MakeData({}, 0)) << updater.Data(); + + updater.Update("foo"); + EXPECT_EQ(updater.Data(), MakeData({{"foo", 1}}, 0)) << updater.Data(); + + updater.Update("bar"); + EXPECT_EQ(updater.Data(), MakeData({{"foo", 1}, {"bar", 1}}, 0)) + << updater.Data(); + + updater.Update("foo"); + updater.Update("foo"); + EXPECT_EQ(updater.Data(), MakeData({{"foo", 3}, {"bar", 1}}, 0)) + << updater.Data(); + + updater.Update("baz"); + // If kinds of entry are over 'max_histogram_buckets', the oldest bucket is + // converted to 'other_bucket_frequency'. + EXPECT_EQ(updater.Data(), MakeData({{"foo", 3}, {"baz", 1}}, 1)) + << updater.Data(); + + updater.Update("foobar"); + // When an entry is dropped out of 'sliding_window_size', existing frequencies + // are recalculated as: + // next_freq = current_freq/sliding_window_size * (sliding_window_size - 1) + // next_others_frequency = (current_others_freq + dropped_entry_freq) + // /sliding_window_size * (sliding_window_size - 1) + // new_freq = 1 + // then + // "foo" = 3/5 * 4 + // "others" = (1 + 1)/5 * 4 + // See lcp_critical_path_predictor_util.cc for detail. + EXPECT_EQ(updater.Data(), MakeData({{"foo", 2.4}, {"foobar", 1}}, 1.6)) + << updater.Data(); +} TEST(IsValidLcppStatTest, Empty) { LcppStat lcpp_stat; @@ -725,71 +796,45 @@ } } -void TestGetLCPPDatabaseKey( - const std::vector<std::pair<std::string, std::string>>& url_keys, - const base::Location& location = FROM_HERE) { - for (const auto& url_key : url_keys) { - const GURL url(url_key.first); - EXPECT_TRUE(IsURLValidForLcpp(url)) << location.ToString() << url_key.first; - const std::optional<std::string> key = GetLCPPDatabaseKey(url); - EXPECT_TRUE(key.has_value()) << location.ToString() << url_key.first; - EXPECT_EQ(url_key.second, *key) << location.ToString() << url_key.first; - } -} - -TEST(LcppKeyTest, GetLCPPDatabaseKey) { - const std::vector<std::pair<std::string, std::string>> url_keys = { - {"http://a.test", "a.test"}, - {"http://a.test/", "a.test"}, - {"http://a.test/foo", "a.test"}, - {"http://a.test/bar?q=c", "a.test"}, - {"http://user:pass@a.test:99/foo;bar?q=a#ref", "a.test"}, - }; - - TestGetLCPPDatabaseKey(url_keys); -} - size_t GetLCPPMultipleKeyMaxPathLength() { static const size_t max_length = base::checked_cast<size_t>( blink::features::kLCPPMultipleKeyMaxPathLength.Get()); return max_length; } -TEST(LcppMultipleKeyTest, GetLCPPDatabaseKey) { +TEST(LcppMultipleKeyTest, GetFirstLevelPath) { base::test::ScopedFeatureList scoped_feature_list_; scoped_feature_list_.InitAndEnableFeature(blink::features::kLCPPMultipleKey); - const std::string long_host = - std::string(ResourcePrefetchPredictorTables::kMaxStringLength - 10, 'a') + - ".test"; const size_t max_path_length = GetLCPPMultipleKeyMaxPathLength(); const std::string long_path = "/" + std::string(max_path_length - 1, 'b'); const std::string too_long_path = "/" + std::string(max_path_length + 1, 'c') + "/bar"; const std::vector<std::pair<std::string, std::string>> url_keys = { - {"http://a.test", "a.test"}, - {"http://user:pass@a.test:99/foo;bar?q=a#ref", "a.test/foo;bar"}, - {"http://a.test/", "a.test"}, - {"http://a.test/foo.html", "a.test"}, - {"http://a.test/foo", "a.test/foo"}, - {"http://a.test/foo/", "a.test/foo"}, - {"http://a.test/foo/bar", "a.test/foo"}, - {"http://a.test/foo/bar/", "a.test/foo"}, - {"http://a.test/foo/bar/baz.com", "a.test/foo"}, - {"http://a.test/bar?q=c", "a.test/bar"}, - {"http://a.test/foo/bar?q=c", "a.test/foo"}, - {"http://a.test" + long_path, "a.test" + long_path}, - {"http://a.test" + long_path + "/bar", "a.test" + long_path}, - {"http://a.test" + long_path + "bar", "a.test"}, - {"http://" + long_host + "/bar", long_host + "/bar"}, - // Both valid but if the concated key is too long, take only host. - {"http://" + long_host + long_path, long_host}, + {"http://a.test", ""}, + {"http://user:pass@a.test:99/foo;bar?q=a#ref", "/foo;bar"}, + {"http://a.test/", ""}, + {"http://a.test/foo.html", ""}, + {"http://a.test/foo", "/foo"}, + {"http://a.test/foo/", "/foo"}, + {"http://a.test/foo/bar", "/foo"}, + {"http://a.test/foo/bar/", "/foo"}, + {"http://a.test/foo/bar/baz.com", "/foo"}, + {"http://a.test/bar?q=c", "/bar"}, + {"http://a.test/foo/bar?q=c", "/foo"}, + {"http://a.test" + long_path, long_path}, + {"http://a.test" + long_path + "/bar", long_path}, + {"http://a.test" + long_path + "bar", ""}, // Too long path is ignored. - {"http://a.test" + too_long_path, "a.test"}, + {"http://a.test" + too_long_path, ""}, // Invalid length path in subdirectory is also ignored. - {"http://a.test/bar" + too_long_path, "a.test/bar"}}; + {"http://a.test/bar" + too_long_path, "/bar"}}; - TestGetLCPPDatabaseKey(url_keys); + for (const auto& url_key : url_keys) { + const GURL url(url_key.first); + EXPECT_TRUE(IsURLValidForLcpp(url)) << url_key.first; + EXPECT_EQ(GetFirstLevelPath(url), url_key.second) << url_key.first; + } } } // namespace predictors
diff --git a/chrome/browser/predictors/loading_predictor_config.cc b/chrome/browser/predictors/loading_predictor_config.cc index 1f9c2357..ffa18693 100644 --- a/chrome/browser/predictors/loading_predictor_config.cc +++ b/chrome/browser/predictors/loading_predictor_config.cc
@@ -45,10 +45,8 @@ features::kLoadingPredictorTableConfig, "max_hosts_to_track", 100)), - max_hosts_to_track_for_lcpp(base::GetFieldTrialParamByFeatureAsInt( - blink::features::kLCPCriticalPathPredictor, - "lcpp_max_hosts_to_track", - 100)), + max_hosts_to_track_for_lcpp( + blink::features::kLCPCriticalPathPredictorMaxHostsToTrack.Get()), max_origins_per_entry(base::GetFieldTrialParamByFeatureAsInt( features::kLoadingPredictorTableConfig, "max_origins_per_entry", @@ -56,14 +54,12 @@ max_consecutive_misses(3), max_redirect_consecutive_misses(5), flush_data_to_disk_delay_seconds(30), - lcpp_histogram_sliding_window_size(base::GetFieldTrialParamByFeatureAsInt( - features::kLoadingPredictorTableConfig, - "lcpp_histogram_sliding_window_size", - 1000)), - max_lcpp_histogram_buckets(base::GetFieldTrialParamByFeatureAsInt( - features::kLoadingPredictorTableConfig, - "max_lcpp_histogram_buckets", - 10)) {} + lcpp_histogram_sliding_window_size( + blink::features::kLCPCriticalPathPredictorHistogramSlidingWindowSize + .Get()), + max_lcpp_histogram_buckets( + blink::features::kLCPCriticalPathPredictorMaxHistogramBuckets.Get()) { +} LoadingPredictorConfig::LoadingPredictorConfig( const LoadingPredictorConfig& other) = default;
diff --git a/chrome/browser/predictors/loading_test_util.cc b/chrome/browser/predictors/loading_test_util.cc index 9b29fd2..1b628ec5 100644 --- a/chrome/browser/predictors/loading_test_util.cc +++ b/chrome/browser/predictors/loading_test_util.cc
@@ -301,23 +301,27 @@ std::ostream& operator<<(std::ostream& os, const LcppData& data) { os << "[" << data.host() << "," << data.last_visit_time() << "]" << std::endl; + os << data.lcpp_stat(); + return os; +} +std::ostream& operator<<(std::ostream& os, const LcppStat& stat) { // Output lcp_element_locator_stat. os << "\t\t" << "lcp_element_locator_stat:" << std::endl; - os << data.lcpp_stat().lcp_element_locator_stat(); + os << stat.lcp_element_locator_stat(); // Output lcp_script_url_stat. os << "\t\t" << "lcp_script_url_stat:" << std::endl; - os << data.lcpp_stat().lcp_script_url_stat(); + os << stat.lcp_script_url_stat(); // Output fetched_font_url_stat. os << "\t\t" << "fetched_font_url_stat:" << std::endl; - os << data.lcpp_stat().fetched_font_url_stat(); + os << stat.fetched_font_url_stat(); // Output fetched_subresource_url_stat. os << "\t\t" << "fetched_subresource_url_stat:" << std::endl; - os << data.lcpp_stat().fetched_subresource_url_stat(); + os << stat.fetched_subresource_url_stat(); return os; }
diff --git a/chrome/browser/predictors/loading_test_util.h b/chrome/browser/predictors/loading_test_util.h index 01c3d05..1bfb240 100644 --- a/chrome/browser/predictors/loading_test_util.h +++ b/chrome/browser/predictors/loading_test_util.h
@@ -123,8 +123,11 @@ std::ostream& operator<<(std::ostream& os, const PreconnectPrediction& prediction); std::ostream& operator<<(std::ostream& os, const LcppData& data); +std::ostream& operator<<(std::ostream& os, const LcppStat& stat); std::ostream& operator<<(std::ostream& os, const LcpElementLocatorBucket& bucket); +std::ostream& operator<<(std::ostream& os, + const LcppStringFrequencyStatData& data); bool operator==(const RedirectData& lhs, const RedirectData& rhs); bool operator==(const RedirectStat& lhs, const RedirectStat& rhs);
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc index 983725c..30fdb569 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -29,6 +29,7 @@ #include "content/public/browser/web_contents.h" #include "net/base/url_util.h" #include "services/network/public/mojom/fetch_api.mojom.h" +#include "third_party/blink/public/common/features.h" #include "url/origin.h" using content::BrowserThread; @@ -70,6 +71,23 @@ return GURL(scheme + "://" + host + ":" + base::NumberToString(port)); } +std::string GetLCPPDatabaseKey(const GURL& url) { + CHECK(IsURLValidForLcpp(url)); + + if (!base::FeatureList::IsEnabled(blink::features::kLCPPMultipleKey)) { + return url.host(); + } + const std::string first_level_path = GetFirstLevelPath(url); + const size_t key_length = url.host().length() + first_level_path.length(); + if (key_length > ResourcePrefetchPredictorTables::kMaxStringLength) { + // The key must not be longer than `kMaxStringLength`. + // Note that we confirmed that url.host() is less than the limit in + // `IsURLValidForLcpp()`. + return url.host(); + } + return url.host() + first_level_path; +} + } // namespace PreconnectRequest::PreconnectRequest(
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc index f36a42bb6..b8f678a 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -32,6 +32,7 @@ #include "net/base/network_isolation_key.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "url/gurl.h" #include "url/origin.h" @@ -132,11 +133,15 @@ } void ResetPredictor(bool small_db = true) { + LoadingPredictorConfig config; + PopulateTestConfig(&config, small_db); + ResetPredictor(config); + } + + void ResetPredictor(const LoadingPredictorConfig& config) { if (loading_predictor_) loading_predictor_->Shutdown(); - LoadingPredictorConfig config; - PopulateTestConfig(&config, small_db); loading_predictor_ = std::make_unique<LoadingPredictor>(config, profile_.get()); predictor_ = loading_predictor_->resource_prefetch_predictor(); @@ -177,6 +182,24 @@ predictor_->LearnLcpp(url, inputs); } + void TestLearnLcppURL( + const std::vector<std::pair<std::string, std::string>>& url_keys, + const base::Location& location = FROM_HERE) { + std::map<std::string, int> frequency; + for (const auto& url_key : url_keys) { + const std::string& url = url_key.first; + const std::string& key = url_key.second; + LearnLcpp(GURL(url), "/#a", {}); + // Confirm 'url' was learned as 'key'. + auto stat = predictor_->GetLcppStat(GURL("http://" + key)); + EXPECT_TRUE(stat) << location.ToString() << url; + LcppData expected; + InitializeLcpElementLocatorBucket(expected, "/#a", ++frequency[key]); + EXPECT_EQ(expected.lcpp_stat(), *stat) + << location.ToString() << url << *stat; + } + } + content::BrowserTaskEnvironment task_environment_; std::unique_ptr<TestingProfile> profile_; scoped_refptr<base::TestSimpleTaskRunner> db_task_runner_; @@ -1321,4 +1344,88 @@ } } +TEST_F(ResourcePrefetchPredictorTest, LcppMaxHosts) { + LoadingPredictorConfig config; + PopulateTestConfig(&config); + config.max_hosts_to_track_for_lcpp = 3u; + ResetPredictor(config); + InitializePredictor(); + + const GURL url_a("http://a.test"); + EXPECT_FALSE(predictor_->GetLcppStat(url_a)); + + LearnLcpp(url_a, "/#a", {}); + EXPECT_TRUE(predictor_->GetLcppStat(url_a)); + + const GURL url_b("http://b.test"); + LearnLcpp(url_b, "/#a", {}); + const GURL url_c("http://c.test"); + LearnLcpp(url_c, "/#a", {}); + EXPECT_TRUE(predictor_->GetLcppStat(url_a)); + EXPECT_TRUE(predictor_->GetLcppStat(url_b)); + EXPECT_TRUE(predictor_->GetLcppStat(url_c)); + + const GURL url_d("http://d.test"); + LearnLcpp(url_d, "/#a", {}); + EXPECT_TRUE(predictor_->GetLcppStat(url_d)); + // Confirm first host is dropped. + EXPECT_FALSE(predictor_->GetLcppStat(url_a)); +} + +TEST_F(ResourcePrefetchPredictorTest, LcppLearnURL) { + const std::vector<std::pair<std::string, std::string>> url_keys = { + {"http://a.test", "a.test"}, + {"http://a.test/", "a.test"}, + {"http://a.test/foo", "a.test"}, + {"http://a.test/bar?q=c", "a.test"}, + {"http://user:pass@a.test:99/foo;bar?q=a#ref", "a.test"}, + }; + + TestLearnLcppURL(url_keys); +} + +TEST_F(ResourcePrefetchPredictorTest, LcppLearnURLMultipleKey) { + base::test::ScopedFeatureList scoped_feature_list_; + scoped_feature_list_.InitAndEnableFeature(blink::features::kLCPPMultipleKey); + LoadingPredictorConfig config; + PopulateTestConfig(&config); + config.max_hosts_to_track_for_lcpp = 100u; + config.lcpp_histogram_sliding_window_size = 10u; + ResetPredictor(config); + InitializePredictor(); + + const std::string long_host = + std::string(ResourcePrefetchPredictorTables::kMaxStringLength - 10, 'a') + + ".test"; + const size_t max_path_length = base::checked_cast<size_t>( + blink::features::kLCPPMultipleKeyMaxPathLength.Get()); + const std::string long_path = "/" + std::string(max_path_length - 1, 'b'); + const std::string too_long_path = + "/" + std::string(max_path_length + 1, 'c') + "/bar"; + const std::vector<std::pair<std::string, std::string>> url_keys = { + {"http://a.test", "a.test"}, + {"http://user:pass@a.test:99/foo;bar?q=a#ref", "a.test/foo;bar"}, + {"http://a.test/", "a.test"}, + {"http://a.test/foo.html", "a.test"}, + {"http://a.test/foo", "a.test/foo"}, + {"http://a.test/foo/", "a.test/foo"}, + {"http://a.test/foo/bar", "a.test/foo"}, + {"http://a.test/foo/bar/", "a.test/foo"}, + {"http://a.test/foo/bar/baz.com", "a.test/foo"}, + {"http://a.test/bar?q=c", "a.test/bar"}, + {"http://a.test/foo/bar?q=c", "a.test/foo"}, + {"http://a.test" + long_path, "a.test" + long_path}, + {"http://a.test" + long_path + "/bar", "a.test" + long_path}, + {"http://a.test" + long_path + "bar", "a.test"}, + {"http://" + long_host + "/bar", long_host + "/bar"}, + // Both valid but if the concated key is too long, take only host. + {"http://" + long_host + long_path, long_host}, + // Too long path is ignored. + {"http://a.test" + too_long_path, "a.test"}, + // Invalid length path in subdirectory is also ignored. + {"http://a.test/bar" + too_long_path, "a.test/bar"}}; + + TestLearnLcppURL(url_keys); +} + } // namespace predictors
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc index 56b59fb..7df2387 100644 --- a/chrome/browser/printing/pwg_raster_converter.cc +++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -105,7 +105,7 @@ // TODO(thestig): Write `data` into shared memory in the first place, to avoid // this memcpy(). - memcpy(memory.mapping.memory(), data->front(), data->size()); + memcpy(memory.mapping.memory(), data->data(), data->size()); pdf_to_pwg_raster_converter_remote_->Convert( std::move(memory.region), settings_, bitmap_settings_, base::BindOnce(&PwgRasterConverterHelper::RunCallback, this));
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc index 3f57f2c..8984b3f 100644 --- a/chrome/browser/profiles/profile_android.cc +++ b/chrome/browser/profiles/profile_android.cc
@@ -26,8 +26,7 @@ namespace jni_zero { template <> -Profile* FromJniType<Profile*, jobject>(JNIEnv* env, - const JavaRef<jobject>& j_profile) { +Profile* FromJniType<Profile*>(JNIEnv* env, const JavaRef<jobject>& j_profile) { return ProfileAndroid::FromProfileAndroid(j_profile); }
diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc index 2476d03..6458ff3 100644 --- a/chrome/browser/profiles/profile_attributes_storage.cc +++ b/chrome/browser/profiles/profile_attributes_storage.cc
@@ -1014,9 +1014,9 @@ base::OnceClosure callback) { cached_avatar_images_[key] = image; - std::unique_ptr<ImageData> data(new ImageData); scoped_refptr<base::RefCountedMemory> png_data = image.As1xPNGBytes(); - data->assign(png_data->front(), png_data->front() + png_data->size()); + auto data = std::make_unique<ImageData>(png_data->size()); + base::span(*data).copy_from(*png_data); // Remove the file from the list of downloads in progress. Note that this list // only contains the high resolution avatars, and not the Gaia profile images.
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java index e0ba586..eb966bb 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudController.java
@@ -84,7 +84,7 @@ private final Activity mActivity; private final ObservableSupplier<Profile> mProfileSupplier; private final ObserverList<Runnable> mReadabilityUpdateObserverList = new ObserverList<>(); - private static final int MAX_URL_ENTRIES = 2000; + private static final int MAX_URL_ENTRIES = 300; private final LruCache<Integer, Boolean> mReadabilityMap = new LruCache<>(MAX_URL_ENTRIES); // the key is the url hash, the value is time it was added to the map private final LruCache<Integer, Long> mReadabilityRequestTimeMap = @@ -128,9 +128,6 @@ // Playback for voice previews @Nullable private Playback mVoicePreviewPlayback; - // TODO(b/322052505): Remove this and just observe mProfileSupplier. - @Nullable private Profile mProfile; - private boolean mOnUserLeaveHint; private boolean mRestoringPlayer; @@ -426,13 +423,12 @@ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public void onProfileAvailable(Profile profile) { - mProfile = profile; mReadabilityHooks = sReadabilityHooksForTesting != null ? sReadabilityHooksForTesting : new ReadAloudReadabilityHooksImpl(mActivity, profile); if (mReadabilityHooks.isEnabled()) { - boolean isAllowed = ReadAloudFeatures.isAllowed(mProfileSupplier.get()); + boolean isAllowed = ReadAloudFeatures.isAllowed(profile); ReadAloudMetrics.recordIsUserEligible(isAllowed); if (!isAllowed) { ReadAloudMetrics.recordIneligibilityReason( @@ -611,7 +607,7 @@ if (mReadabilityHooks == null) { return; } - if (mProfile == null || !mProfile.isNativeInitialized()) { + if (mProfileSupplier.get() == null || !mProfileSupplier.get().isNativeInitialized()) { return; } if (!isURLReadAloudSupported(url)) { @@ -679,8 +675,8 @@ if (tab == null || tab.getUrl() == null || tab.getWebContents() == null - || mProfile == null - || !mProfile.isNativeInitialized()) { + || mProfileSupplier.get() == null + || !mProfileSupplier.get().isNativeInitialized()) { return false; } @@ -745,6 +741,11 @@ ReadAloudMetrics.recordPlaybackWithoutReadabilityCheck( entrypoint, Entrypoint.NUM_ENTRIES); } + // Should rarely ever happen since the profile has to be established for a readability check + // to show the entrypoint. + if (mProfileSupplier.get() == null) { + return; + } extractDateModified(tab) .then( timestamp -> { @@ -1187,7 +1188,7 @@ private Promise<Playback> createPlayback(PlaybackArgs args) { final var promise = new Promise<Playback>(); - if (mProfile == null || !mProfile.isNativeInitialized()) { + if (mProfileSupplier.get() == null || !mProfileSupplier.get().isNativeInitialized()) { promise.reject(new Exception("missing profile")); return promise; } @@ -1350,7 +1351,8 @@ resetCurrentPlayback(); mOnUserLeaveHint = false; } else if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES - && mStateToRestoreOnBringingToForeground != null) { + && mStateToRestoreOnBringingToForeground != null + && mProfileSupplier.get() != null) { mStateToRestoreOnBringingToForeground.restore(); mStateToRestoreOnBringingToForeground = null; mOnUserLeaveHint = false;
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java index 9b9d80e..9224cfdc 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/ReadAloudControllerUnitTest.java
@@ -334,11 +334,7 @@ verify(mPlayback, never()).release(); // now start playing a tab - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); // reload some other tab, playback should keep going MockTab newTab = mTabModelSelector.addMockTab(); @@ -376,12 +372,7 @@ verify(mPlayback, never()).release(); // now start playing a tab - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); // change attachement of some other tab, playback should keep going MockTab newTab = mTabModelSelector.addMockTab(); @@ -405,12 +396,7 @@ @Test public void testOnActivityAttachmentChanged_saveAndRestoreState() { // start playing a tab - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); // now detach the playing tab mController @@ -453,11 +439,7 @@ assertFalse(mController.isRestoringPlayer()); // Start playing a tab, detach, restore - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); mController .getTabModelTabObserverforTests() .onActivityAttachmentChanged(mTab, /* window= */ null); @@ -505,11 +487,7 @@ verify(mPlayback, never()).release(); // now start playing a tab - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); // close some other tab, playback should keep going MockTab newTab = mTabModelSelector.addMockTab(); @@ -761,17 +739,7 @@ @Test public void testPlayTab() { - mFakeTranslateBridge.setCurrentLanguage("en"); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - - onPlaybackSuccess(mPlayback); - verify(mPlayerCoordinator, times(1)) - .playbackReady(eq(mPlayback), eq(PlaybackListener.State.PLAYING)); + requestAndStartPlayback(); verify(mPlayerCoordinator).addObserver(mController); // test that previous playback is released when another playback is called @@ -1042,17 +1010,7 @@ @Test public void testStopPlayback() { // Play tab - mFakeTranslateBridge.setCurrentLanguage("en"); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - - onPlaybackSuccess(mPlayback); - verify(mPlayerCoordinator, times(1)) - .playbackReady(eq(mPlayback), eq(PlaybackListener.State.PLAYING)); + requestAndStartPlayback(); // Stop playback mController.maybeStopPlayback(mTab); @@ -1250,10 +1208,7 @@ @Test public void testSetVoiceWhilePaused() { // Play tab. - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks).createPlayback(any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); verify(mPlayback).addListener(mPlaybackListenerCaptor.capture()); reset(mPlaybackHooks); reset(mPlayback); @@ -1935,10 +1890,7 @@ final String histogramName = ReadAloudMetrics.IS_TAB_PLAYBACK_CREATION_SUCCESSFUL; var histogram = HistogramWatcher.newSingleRecordWatcher(histogramName, true); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks).createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); histogram.assertExpected(); } @@ -1973,12 +1925,7 @@ HistogramWatcher.newSingleRecordWatcher( histogramName, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); histogram.assertExpected(); } @@ -2069,13 +2016,7 @@ @Test public void testNavigateToPlayingTab() { // Play tab. - mFakeTranslateBridge.setCurrentLanguage("en"); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks).createPlayback(any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); - verify(mPlayback, times(1)).play(); + requestAndStartPlayback(); MockTab newTab = mTabModelSelector.addMockTab(); mTabModelSelector @@ -2154,12 +2095,7 @@ @Test public void testDestroy() { // Play tab - mFakeTranslateBridge.setCurrentLanguage("en"); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - verify(mPlaybackHooks).createPlayback(any(), mPlaybackCallbackCaptor.capture()); - onPlaybackSuccess(mPlayback); + requestAndStartPlayback(); // Destroy should clean up playback, UI, synthetic trials, and more mController.destroy(); @@ -2327,19 +2263,7 @@ @Test public void testPlayTabWithDateExtraction() { - mFakeTranslateBridge.setCurrentLanguage("en"); - - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - - resolvePromises(); - - verify(mPlaybackHooks, times(1)) - .createPlayback(Mockito.any(), mPlaybackCallbackCaptor.capture()); - - onPlaybackSuccess(mPlayback); - verify(mPlayerCoordinator, times(1)) - .playbackReady(eq(mPlayback), eq(PlaybackListener.State.PLAYING)); + requestAndStartPlayback(); verify(mPlayerCoordinator).addObserver(mController); verify(mPlaybackHooks, times(1)).createPlayback(mPlaybackArgsCaptor.capture(), any()); @@ -2351,10 +2275,7 @@ public void testLogDateExtraction_hasDateModified() { mFakeTranslateBridge.setCurrentLanguage("en"); var histogram = HistogramWatcher.newSingleRecordWatcher("ReadAloud.HasDateModified", true); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - resolvePromises(); - + requestAndStartPlayback(); histogram.assertExpected(); } @@ -2366,10 +2287,7 @@ failedPromise.reject(new Exception("")); var histogram = HistogramWatcher.newSingleRecordWatcher("ReadAloud.HasDateModified", false); - mTab.setGurlOverrideForTesting(new GURL("https://en.wikipedia.org/wiki/Google")); - mController.playTab(mTab, ReadAloudController.Entrypoint.MAGIC_TOOLBAR); - - resolvePromises(); + requestAndStartPlayback(); histogram.assertExpected(); }
diff --git a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java index 0a71a21..dff4a23 100644 --- a/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java +++ b/chrome/browser/readaloud/android/java/src/org/chromium/chrome/browser/readaloud/player/mini/MiniPlayerMediator.java
@@ -202,6 +202,7 @@ } private void growBottomControls() { + mBrowserControlsSizer.notifyBackgroundColor(mModel.get(Properties.BACKGROUND_COLOR_ARGB)); setBottomControlsHeight( mBrowserControlsSizer.getBottomControlsHeight() + mLayoutHeightPx, mLayoutHeightPx); }
diff --git a/chrome/browser/resources/ash/settings/controls/settings_dropdown_menu.html b/chrome/browser/resources/ash/settings/controls/settings_dropdown_menu.html index db40287..b997940b 100644 --- a/chrome/browser/resources/ash/settings/controls/settings_dropdown_menu.html +++ b/chrome/browser/resources/ash/settings/controls/settings_dropdown_menu.html
@@ -32,7 +32,8 @@ </option> </template> <option value="[[notFoundValue]]" - disabled="[[!showNotFoundValue_(menuOptions, pref.value)]]"> + disabled="[[!showNotFoundValue_(menuOptions, pref.value)]]" + aria-hidden="[[!showNotFoundValue_(menuOptions, pref.value)]]"> $i18n{custom} </option> </select>
diff --git a/chrome/browser/resources/ash/settings/device_page/per_device_touchpad_subsection.html b/chrome/browser/resources/ash/settings/device_page/per_device_touchpad_subsection.html index e3e9f4d..387fc79 100644 --- a/chrome/browser/resources/ash/settings/device_page/per_device_touchpad_subsection.html +++ b/chrome/browser/resources/ash/settings/device_page/per_device_touchpad_subsection.html
@@ -73,7 +73,7 @@ </settings-slider> </div> <div class="settings-box two-line" id="touchpadHapticFeedbackRow" - on-click="onTouchpadHapticFeedbackRowClicked_"> + on-click="onTouchpadHapticFeedbackRowClicked_" actionable-row> <div class="start settings-box-text"> <div>$i18n{touchpadHapticFeedbackTitle}</div> <div class="secondary"> @@ -96,7 +96,7 @@ </div> </template> <div class="settings-box bottom-divider" id="reverseScrollRow" - on-click="onTouchpadReverseScrollRowClicked_"> + on-click="onTouchpadReverseScrollRowClicked_" actionable-row> <div class="start settings-box-text"> <localized-link aria-describedby="touchpadName"
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_page.html b/chrome/browser/resources/ash/settings/internet_page/internet_page.html index 1e4558e..67f70a2 100644 --- a/chrome/browser/resources/ash/settings/internet_page/internet_page.html +++ b/chrome/browser/resources/ash/settings/internet_page/internet_page.html
@@ -31,6 +31,11 @@ position: relative; top: -22px; } + + #apnSubpageTitleExtra { + display: flex; + align-items: center; + } </style> <os-settings-animated-pages id="pages" section="[[section_]]"> <div route-path="default"> @@ -132,12 +137,21 @@ <template is="dom-if" route-path="/apn" restamp> <os-settings-subpage page-title="$i18n{internetApnPageTitle}"> - <div slot="subpage-title-extra"> + <div id="apnSubpageTitleExtra" slot="subpage-title-extra"> + <template is="dom-if" if="[[isApnManaged_(globalPolicy_)]]"> + <!-- TODO(b/335486874): Fix tooltip in RTL. --> + <cr-tooltip-icon id="apnManagedIcon" + tooltip-text="$i18n{controlledSettingPolicy}" + icon-class="cr20:domain" + tooltip-position="left"> + </cr-tooltip-icon> + </template> <cr-icon-button id="apnActionMenuButton" class="icon-more-vert" on-click="onApnMenuButtonClicked_" focus-row-control focus-type="menu" deep-link-focus-id$="[[Setting.kCellularAddApn]]" - title="$i18n{moreActions}"> + title="$i18n{moreActions}" + disabled="[[isApnManaged_(globalPolicy_)]]"> </cr-icon-button> </div> <apn-subpage id="apnSubpage"
diff --git a/chrome/browser/resources/ash/settings/internet_page/internet_page.ts b/chrome/browser/resources/ash/settings/internet_page/internet_page.ts index 60404b1..3fcc63e 100644 --- a/chrome/browser/resources/ash/settings/internet_page/internet_page.ts +++ b/chrome/browser/resources/ash/settings/internet_page/internet_page.ts
@@ -15,6 +15,7 @@ import 'chrome://resources/ash/common/cr_elements/cr_toast/cr_toast.js'; import 'chrome://resources/ash/common/cr_elements/icons.html.js'; import 'chrome://resources/ash/common/cr_elements/policy/cr_policy_indicator.js'; +import 'chrome://resources/ash/common/cr_elements/policy/cr_tooltip_icon.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import '/shared/settings/prefs/prefs.js'; @@ -349,6 +350,14 @@ }, }, + isApnPoliciesEnabled_: { + type: Boolean, + value() { + return loadTimeData.valueExists('isApnPoliciesEnabled') && + loadTimeData.getBoolean('isApnPoliciesEnabled'); + }, + }, + /** * Whether the 'Add custom APN' button is disabled. */ @@ -384,6 +393,7 @@ private isNumCustomApnsLimitReached_: boolean; private isInstantHotspotRebrandEnabled_: boolean; private isHotspotFeatureEnabled_: boolean; + private isApnPoliciesEnabled_: boolean; private isAddingBuiltInVpnProhibited_: boolean; private knownNetworksType_: NetworkType; private networkConfig_: CrosNetworkConfigInterface; @@ -1061,6 +1071,16 @@ apnSubpage.openApnSelectionDialog(); } + private isApnManaged_(globalPolicy: GlobalPolicy|undefined): boolean { + if (!this.isApnRevampEnabled_ || !this.isApnPoliciesEnabled_) { + return false; + } + if (!globalPolicy) { + return false; + } + return !globalPolicy.allowApnModification; + } + private onShowPasspointDetails_(event: CustomEvent<PasspointSubscription>): void { this.passpointSubscription_ = event.detail;
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.html b/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.html index 7e20aa0a..dc5c9875 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.html +++ b/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.html
@@ -142,13 +142,16 @@ $i18n{caretBlinkIntervalDescription} </div> </div> - <settings-dropdown-menu - id="caretBlinkIntervalMenu" - pref="{{prefs.settings.a11y.caret.blink_interval}}" - label="$i18n{caretBlinkIntervalLabel}" - menu-options="[[caretBlinkIntervalMenuOptions_]]" - deep-link-focus-id$="[[Setting.kCaretBlinkInterval]]"> - </settings-dropdown-menu> + <settings-slider + id="caretBlinkIntervalSlider" + pref="{{caretBlinkIntervalVirtualPref_}}" + show-markers + label-aria="$i18n{caretBlinkIntervalLabel}" + label-min="$i18n{caretBlinkIntervalOff}" + label-max="$i18n{caretBlinkIntervalFast}" + ticks="[[computeCaretBlinkIntervalTicks_()]]" + deep-link-focus-id$="[[Setting.kCaretBlinkInterval]]"> + </settings-slider> </div> </template> <settings-toggle-button
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.ts b/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.ts index 26bd44af..4c9d0eb1 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/keyboard_and_text_input_page.ts
@@ -20,6 +20,7 @@ import './change_dictation_locale_dialog.js'; import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; +import {SliderTick} from 'chrome://resources/ash/common/cr_elements/cr_slider/cr_slider.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {WebUiListenerMixin} from 'chrome://resources/ash/common/cr_elements/web_ui_listener_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -69,29 +70,10 @@ }, }, - caretBlinkIntervalMenuOptions_: { - type: Array, - value() { - return [ - // TODO(b:259374492): Pick values based on UX, except for 500, which - // is the current default and should always be available and 0, - // which is the value meaning hold the cursor steady and do not - // blink. - {value: 0, name: loadTimeData.getString('caretBlinkIntervalOff')}, - { - value: 800, - name: loadTimeData.getString('caretBlinkIntervalSlow'), - }, - { - value: loadTimeData.getInteger('defaultCaretBlinkIntervalMs'), - name: loadTimeData.getString('caretBlinkIntervalNormal'), - }, - { - value: 350, - name: loadTimeData.getString('caretBlinkIntervalFast'), - }, - ]; - }, + caretBlinkIntervalVirtualPref_: { + type: Object, + computed: 'computeCaretBlinkIntervalVirtualPref_(' + + 'prefs.settings.a11y.caret.blink_interval.value)', }, dictationLocaleMenuSubtitle_: { @@ -170,6 +152,13 @@ }; } + static get observers() { + return [ + 'updateCaretBlinkIntervalFromVirtualPref_(' + + 'caretBlinkIntervalVirtualPref_.*)', + ]; + } + private dictationLearnMoreUrl_: string; private dictationLocaleMenuSubtitle_: string; private dictationLocaleOptions_: LocaleInfo[]; @@ -181,9 +170,14 @@ chrome.settingsPrivate.PrefObject<boolean>; private keyboardAndTextInputBrowserProxy_: KeyboardAndTextInputPageBrowserProxy; - private stickyKeysEnabledPref_: chrome.settingsPrivate.PrefObject<boolean>; + private stickyKeysEnabledVirtualPref_: + chrome.settingsPrivate.PrefObject<boolean>; private showDictationLocaleMenu_: boolean; private useDictationLocaleSubtitleOverride_: boolean; + private caretBlinkIntervalVirtualPref_: + chrome.settingsPrivate.PrefObject<number>; + private defaultCaretBlinkRateMs_: number; + private caretBlinkIntervalOffSliderValue_ = 40; constructor() { super(); @@ -197,6 +191,9 @@ this.dictationLocaleSubtitleOverride_ = ''; this.useDictationLocaleSubtitleOverride_ = false; + + this.defaultCaretBlinkRateMs_ = + loadTimeData.getInteger('defaultCaretBlinkIntervalMs'); } override ready(): void { @@ -339,6 +336,62 @@ }; } + private computeCaretBlinkIntervalVirtualPref_(): + chrome.settingsPrivate.PrefObject<number> { + if (!this.isAccessibilityCaretBlinkIntervalSettingEnabled_ || !this.prefs) { + return { + type: chrome.settingsPrivate.PrefType.NUMBER, + value: this.defaultCaretBlinkRateMs_, + key: 'caret_blink_interval_virtual_pref', + }; + } + const blinkIntervalMs = + this.getPref<number>('settings.a11y.caret.blink_interval').value; + let value = this.caretBlinkIntervalOffSliderValue_; + if (blinkIntervalMs > 0) { + value = Math.round(this.defaultCaretBlinkRateMs_ / blinkIntervalMs * 100); + } + return { + type: chrome.settingsPrivate.PrefType.NUMBER, + value, + key: 'caret_blink_interval_virtual_pref', + }; + } + + private updateCaretBlinkIntervalFromVirtualPref_(): void { + if (!this.isAccessibilityCaretBlinkIntervalSettingEnabled_) { + return; + } + const percentage = this.caretBlinkIntervalVirtualPref_.value; + // Default: do not blink. + let delayMs = 0; + if (percentage > this.caretBlinkIntervalOffSliderValue_) { + delayMs = Math.round(this.defaultCaretBlinkRateMs_ / (percentage / 100)); + } + this.setPrefValue('settings.a11y.caret.blink_interval', delayMs); + } + + private computeCaretBlinkIntervalTicks_(): SliderTick[] { + const ticks = [ + { + value: this.caretBlinkIntervalOffSliderValue_, + ariaValue: 0, + label: this.i18n('caretBlinkIntervalOff'), + }, + ]; + for (let i = this.caretBlinkIntervalOffSliderValue_ + 10; i <= 150; + i += 10) { + const label = i === 100 ? this.i18n('defaultPercentage', i) : + this.i18n('percentage', i); + ticks.push({ + value: i, + ariaValue: i, + label, + }); + } + return ticks; + } + private updateFocusHighlightEnabledVirtualPref_(): void { // Focus highlight is automatically disabled when ChromeVox is // enabled, although the underlying pref is unchanged (allows
diff --git a/chrome/browser/resources/ash/settings/settings_shared.css b/chrome/browser/resources/ash/settings/settings_shared.css index c701e23..6a15d53 100644 --- a/chrome/browser/resources/ash/settings/settings_shared.css +++ b/chrome/browser/resources/ash/settings/settings_shared.css
@@ -295,6 +295,28 @@ flex: auto; } +/* A settings-box with the actionable-row attribute can be interacted with on + * click. Do not use this attribute for settings that are not interactable by + * clicking on the row. */ +.settings-box[actionable-row] { + cursor: pointer; +} + +.settings-box[actionable-row]:hover { + background-color: var(--cr-hover-background-color); +} + +.settings-box[actionable-row]:active { + background-color: var(--cr-active-background-color); +} + +/* Do not show hover or active states for cr-icon-buttons that are + * embedded within the row to avoid showing multiple layers of + * backgrounds. */ +.settings-box[actionable-row] cr-icon-button { + --cr-icon-button-hover-background-color: transparent; + --cr-icon-button-active-background-color: transparent; +} /* For grouping elements with common flex options. */ .settings-row { align-items: center;
diff --git a/chrome/browser/resources/chromeos/accessibility/OWNERS b/chrome/browser/resources/chromeos/accessibility/OWNERS index 35ca97e..bfecbc9 100644 --- a/chrome/browser/resources/chromeos/accessibility/OWNERS +++ b/chrome/browser/resources/chromeos/accessibility/OWNERS
@@ -1 +1,2 @@ file://ash/accessibility/OWNERS +francisjp@google.com \ No newline at end of file
diff --git a/chrome/browser/resources/downloads/item.html b/chrome/browser/resources/downloads/item.html index a5491fb..8be2218 100644 --- a/chrome/browser/resources/downloads/item.html +++ b/chrome/browser/resources/downloads/item.html
@@ -600,15 +600,18 @@ </div> </div> </div> - <template is="dom-if" if="[[showEsbPromotion]]"> - <!-- TODO(crbug.com/333734490): Replace icon with branded gshield icon. --> - <cr-link-row - id="esb-download-row-promo" - start-icon="downloads:shield" - external - on-click="onEsbPromotionClick_" - button-aria-description="$i18n{esbDownloadRowPromoA11y}" - label="$i18n{esbDownloadRowPromoString}"> - </cr-link-row> - </template> + <if expr="_google_chrome"> + <template is="dom-if" if="[[showEsbPromotion]]"> + <!-- TODO(crbug.com/333734490): Replace icon with branded gshield icon. + --> + <cr-link-row + id="esb-download-row-promo" + start-icon="downloads:shield" + external + on-click="onEsbPromotionClick_" + button-aria-description="$i18n{esbDownloadRowPromoA11y}" + label="$i18n{esbDownloadRowPromoString}"> + </cr-link-row> + </template> + </if> </div>
diff --git a/chrome/browser/resources/downloads/item.ts b/chrome/browser/resources/downloads/item.ts index 9add134..8e6ccc7 100644 --- a/chrome/browser/resources/downloads/item.ts +++ b/chrome/browser/resources/downloads/item.ts
@@ -8,7 +8,9 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_icons.css.js'; import 'chrome://resources/cr_elements/cr_hidden_style.css.js'; +// <if expr="_google_chrome"> import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; +// </if> import 'chrome://resources/cr_elements/icons.html.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import 'chrome://resources/js/action_link.js'; @@ -186,10 +188,12 @@ value: () => loadTimeData.getBoolean('improvedDownloadWarningsUX'), }, + // <if expr="_google_chrome"> showEsbPromotion: { type: Boolean, value: false, }, + // </if> useFileIcon_: Boolean, }; @@ -207,7 +211,9 @@ } data: MojomData; + // <if expr="_google_chrome"> showEsbPromotion: boolean; + // </if> private mojoHandler_: PageHandlerInterface|null = null; private controlledBy_: string; private iconAriaLabel_: string; @@ -833,10 +839,12 @@ }); } + // <if expr="_google_chrome"> private onEsbPromotionClick_() { assert(!!this.mojoHandler_); this.mojoHandler_.openEsbSettings(); } + // </if> private onMoreActionsClick_() { assert(this.improvedDownloadWarningsUx_);
diff --git a/chrome/browser/resources/downloads/manager.ts b/chrome/browser/resources/downloads/manager.ts index 2d4b589e..4b6790d2 100644 --- a/chrome/browser/resources/downloads/manager.ts +++ b/chrome/browser/resources/downloads/manager.ts
@@ -93,6 +93,7 @@ value: '', }, + // <if expr="_google_chrome"> firstDangerousItemId_: { type: String, value: '', @@ -107,6 +108,7 @@ type: Boolean, value: () => loadTimeData.getBoolean('esbDownloadRowPromo'), }, + // </if> lastFocused_: Object, @@ -124,9 +126,11 @@ private inSearchMode_: boolean; private spinnerActive_: boolean; private bypassDialogItemId_: string; + // <if expr="_google_chrome"> private firstDangerousItemId_: string; private esbDownloadRowPromo_: boolean; private isEligibleForEsbPromo_: boolean; + // </if> private announcerDebouncer_: Debouncer|null = null; private mojoHandler_: PageHandlerInterface; @@ -187,9 +191,11 @@ toastManager.shadowRoot!.querySelector<HTMLElement>('#toast')!.onclick = e => this.onToastClicked_(e); + // <if expr="_google_chrome"> this.mojoHandler_!.isEligibleForEsbPromo().then((result) => { this.isEligibleForEsbPromo_ = result.result; }); + // </if> } override disconnectedCallback() { @@ -210,6 +216,7 @@ } } + // <if expr="_google_chrome"> // Evaluates user eligbility for an esb promotion on the most recent dangerous // download. It does this by traversing the array of downloads and the first // dangerous download it comes across will have the promotion (guarantees the @@ -223,6 +230,7 @@ } return this.firstDangerousItemId_ === item.id; } + // </if> private shouldShowBypassWarningDialog_(): boolean { return this.bypassDialogItemId_ !== '';
diff --git a/chrome/browser/resources/history/app.html b/chrome/browser/resources/history/app.html index 6364d23..f49cbdc2 100644 --- a/chrome/browser/resources/history/app.html +++ b/chrome/browser/resources/history/app.html
@@ -134,6 +134,7 @@ <div class="history-cards"> <history-embeddings-promo></history-embeddings-promo> <cr-history-embeddings-filter-chips + time-range-start="[[queryStateAfterDate_]]" show-results-by-group="[[ getShowResultsByGroup_(selectedPage_)]]" on-show-results-by-group-changed="onShowResultsByGroupChanged_" @@ -143,7 +144,7 @@ if="[[shouldShowHistoryEmbeddings_(queryState_.searchTerm)]]"> <cr-history-embeddings search-query="[[queryState_.searchTerm]]" - time-range-start="[[timeRangeStart_]]" + time-range-start="[[queryStateAfterDate_]]" on-more-from-site-click="onHistoryEmbeddingsItemMoreFromSiteClick_" on-remove-item-click="onHistoryEmbeddingsItemRemoveClick_"> </cr-history-embeddings>
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts index c260f67..ebf907c 100644 --- a/chrome/browser/resources/history/app.ts +++ b/chrome/browser/resources/history/app.ts
@@ -248,6 +248,11 @@ }, scrollTarget_: Object, + + queryStateAfterDate_: { + type: Object, + computed: 'computeQueryStateAfterDate_(queryState_.after)', + }, }; } @@ -271,7 +276,7 @@ private toolbarShadow_: boolean; private historyClustersViewStartTime_: Date|null = null; private scrollTarget_: HTMLElement; - private timeRangeStart_?: Date; + private queryStateAfterDate_?: Date; constructor() { super(); @@ -708,7 +713,21 @@ } private onSelectedSuggestionChanged_(e: CustomEvent<{value: Suggestion}>) { - this.timeRangeStart_ = e.detail.value?.timeRangeStart; + this.fire_('change-query', { + search: this.queryState_.searchTerm, + after: e.detail.value?.timeRangeStart.toISOString().split('T')[0], + }); + } + + private computeQueryStateAfterDate_(): Date|undefined { + const afterString = this.queryState_.after; + if (!afterString) { + return undefined; + } + + const afterDate = new Date(afterString); + afterDate.setHours(0, 0, 0, 0); + return afterDate; } private onHistoryEmbeddingsItemMoreFromSiteClick_(
diff --git a/chrome/browser/resources/history/externs.ts b/chrome/browser/resources/history/externs.ts index 022c3b63..e271b6f 100644 --- a/chrome/browser/resources/history/externs.ts +++ b/chrome/browser/resources/history/externs.ts
@@ -96,6 +96,7 @@ incremental: boolean; querying: boolean; searchTerm: string; + after?: string; } export interface QueryResult {
diff --git a/chrome/browser/resources/history/query_manager.ts b/chrome/browser/resources/history/query_manager.ts index 49cbd44..00dcc2b4 100644 --- a/chrome/browser/resources/history/query_manager.ts +++ b/chrome/browser/resources/history/query_manager.ts
@@ -90,21 +90,31 @@ promise.then(result => this.onQueryResult_(result), () => {}); } - private onChangeQuery_(e: CustomEvent<{search?: string}>) { + private onChangeQuery_(e: CustomEvent<{search?: string, after?: string}>) { const changes = e.detail; - let needsUpdate = false; + + let needsToRequery = false; + let needsToUpdateRouter = false; if (changes.search !== null && changes.search !== this.queryState.searchTerm) { this.set('queryState.searchTerm', changes.search); - needsUpdate = true; + needsToRequery = true; + needsToUpdateRouter = true; } - if (needsUpdate) { + if (changes.after !== null && + changes.after !== this.queryState.after) { + this.set('queryState.after', changes.after); + needsToUpdateRouter = true; + } + + if (needsToRequery) { this.queryHistory_(false); - if (this.router) { - this.router.serializeUrl(); - } + } + + if (needsToUpdateRouter && this.router) { + this.router.serializeUrl(); } }
diff --git a/chrome/browser/resources/history/router.ts b/chrome/browser/resources/history/router.ts index e1eef50e..9cd94ce 100644 --- a/chrome/browser/resources/history/router.ts +++ b/chrome/browser/resources/history/router.ts
@@ -67,10 +67,11 @@ lastSelectedTab: number; selectedPage: string; queryState: QueryState; + timeRangeStart?: Date; private parsing_: boolean = false; private debouncer_: Debouncer|null = null; private query_: string; - private queryParams_: {q: string}; + private queryParams_: {q: string, after?: string}; private path_: string; private urlQuery_: string; @@ -112,6 +113,7 @@ // the outcome. this.path_ = '/' + path; this.set('queryParams_.q', this.queryState.searchTerm || null); + this.set('queryParams_.after', this.queryState.after || null); } private selectedPageChanged_() { @@ -124,7 +126,7 @@ private parseUrl_() { this.parsing_ = true; - const changes: {search: string} = {search: ''}; + const changes: {search: string, after?: string} = {search: ''}; const sections = this.path_.substr(1).split('/'); const page = sections[0] || (window.location.search ? 'history' : @@ -132,6 +134,15 @@ changes.search = this.queryParams_.q || ''; + let after = ''; + if (this.queryParams_.after) { + const afterAsDate = new Date(this.queryParams_.after); + if (!isNaN(afterAsDate.getTime())) { + after = this.queryParams_.after; + } + } + changes.after = after; + // Must change selectedPage before `change-query`, otherwise the // query-manager will call serializeUrl() with the old page. this.selectedPage = page;
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.html b/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.html index c1c39ca..d0dc56d6 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.html +++ b/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.html
@@ -1,5 +1,10 @@ <ntp-module-header-v2 id="moduleHeaderElementV2" - header-text="[[i18n('modulesTodayCalendarHeader')]]"> -</ntp-module-header-v2> -<p>[[calendarSource_]]</p> \ No newline at end of file + header-text="[[sourceTitle_]]" + menu-item-groups="[[getMenuItemGroups_(sourceDisableText_)]]" + more-actions-text="[[i18nRecursive('', + 'modulesMoreActions', + sourceTitle_)]]" + on-disable-button-click="onDisableButtonClick_" + on-menu-button-click="onMenuButtonClick_"> +</ntp-module-header-v2> \ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.ts b/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.ts index 0cc5fb46..d697a07 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.ts +++ b/chrome/browser/resources/new_tab_page/modules/v2/calendar/module.ts
@@ -6,8 +6,9 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {I18nMixin} from '../../../i18n_setup.js'; +import {I18nMixin, loadTimeData} from '../../../i18n_setup.js'; import {ModuleDescriptor} from '../../module_descriptor.js'; +import type {MenuItem, ModuleHeaderElementV2} from '../module_header.js'; import {getTemplate} from './module.html.js'; @@ -16,6 +17,12 @@ OUTLOOK, } +export interface CalendarModuleElement { + $: { + moduleHeaderElementV2: ModuleHeaderElementV2, + }; +} + /** * The Calendar module, which serves as an inside look in to upcoming events on * a user's Google Calendar or Microsoft Outlook. @@ -32,15 +39,73 @@ static get properties() { return { - calendarSource_: Object, + calendarSource_: { + type: Object, + observer: 'setSourceText_', + }, + sourceDisableText_: String, + sourceTitle_: String, }; } private calendarSource_: CalendarSource; + private sourceDisableText_: string = ''; + private sourceTitle_: string = ''; constructor(calendarSource: CalendarSource) { super(); this.calendarSource_ = calendarSource; + this.setSourceText_(); + } + + private setSourceText_() { + switch(this.calendarSource_) { + case CalendarSource.GOOGLE: + this.sourceTitle_ = this.i18n('modulesGoogleCalendarTitle'); + this.sourceDisableText_ = + this.i18n('modulesGoogleCalendarDisableButtonText'); + break; + case CalendarSource.OUTLOOK: + this.sourceTitle_ = this.i18n('modulesOutlookCalendarTitle'); + this.sourceDisableText_ = + this.i18n('modulesOutlookCalendarDisableButtonText'); + break; + } + } + + private getMenuItemGroups_(): MenuItem[][] { + return [ + [ + { + action: 'disable', + icon: 'modules:block', + text: this.sourceDisableText_, + }, + ], + [ + { + action: 'customize-module', + icon: 'modules:tune', + text: this.i18n('modulesCustomizeButtonText'), + }, + ], + ]; + } + + private onDisableButtonClick_() { + const disableEvent = new CustomEvent('disable-module', { + composed: true, + detail: { + message: loadTimeData.getStringF( + 'disableModuleToastMessage', + this.sourceTitle_), + }, + }); + this.dispatchEvent(disableEvent); + } + + private onMenuButtonClick_(e: Event) { + this.$.moduleHeaderElementV2.showAt(e); } }
diff --git a/chrome/browser/resources/settings/images/gtmooc_cookie.svg b/chrome/browser/resources/settings/images/gtmooc_cookie.svg index a0eb893..cfb2a881 100644 --- a/chrome/browser/resources/settings/images/gtmooc_cookie.svg +++ b/chrome/browser/resources/settings/images/gtmooc_cookie.svg
@@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="43" height="44" fill="none" viewBox="0 0 43 44"><mask id="b" width="42" height="36" x="1" y="2" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="42" height="35" x="1" y="2.8" fill="#6DD58C" rx="17.5"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="42" height="35" x="1" y="2.8" fill="#6DD58C" rx="17.5"/></g><g filter="url(#c)"><rect width="2.039" height="6.118" x="14.474" y="26.6" fill="#146C2E" rx="1.02" transform="rotate(45 14.474 26.6)"/><rect width="4.2" height="13.3" x="11.804" y="27.74" fill="#146C2E" rx="2.1" transform="rotate(45 11.804 27.74)"/><circle cx="22" cy="20.3" r="9.8" stroke="#198639" stroke-width="1.4"/></g><circle cx="16.4" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="22" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="27.6" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="22" cy="20.3" r="7.7" fill="url(#d)"/><circle cx="36.7" cy="13.301" r="1.4" fill="#fff"/><circle cx="40.9" cy="13.301" r="1.4" fill="#fff"/><circle cx="3.1" cy="25.899" r="1.4" fill="#fff"/><circle cx="7.3" cy="25.899" r="1.4" fill="#fff"/><defs><filter id="a" width="70" height="63" x="-13" y="-11.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14652" stdDeviation="7"/></filter><filter id="c" width="34.831" height="35.044" x=".469" y="8.401" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1.4"/><feGaussianBlur stdDeviation="1.4"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_1540_14652"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_1540_14652" result="shape"/></filter><linearGradient id="d" x1="16.225" x2="26.492" y1="15.488" y2="25.433" gradientUnits="userSpaceOnUse"><stop stop-color="#37BE5F"/><stop offset=".71" stop-color="#198639" stop-opacity="0"/></linearGradient></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="none" viewBox="0 0 42 42"><mask id="b" width="42" height="42" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#FCC934" rx="11.503"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#FCC934" rx="11.503"/></g><path stroke="#fff" stroke-width="1.4" d="M15.615 7H7v8.615M26.385 7H35v8.615M15.615 35H7v-8.615M26.385 35H35v-8.615"/><path fill="url(#c)" fill-rule="evenodd" d="M23.698 15.344a.975.975 0 0 0-1.098-.458 4.199 4.199 0 0 1-5.016-2.406c-.182-.433-.69-.69-1.084-.436a9.13 9.13 0 1 0 12.724 12.433c.225-.37.016-.835-.366-1.038a4.194 4.194 0 0 1-2.08-4.806c.142-.523-.2-1.16-.716-1.329a4.207 4.207 0 0 1-2.364-1.96Z" clip-rule="evenodd"/><circle cx="16.636" cy="17.206" r="1.241" fill="#996322"/><circle cx="21.6" cy="19.689" r="1.241" fill="#996322"/><path fill="#996322" fill-rule="evenodd" d="M26.75 18.744a1.241 1.241 0 1 0-.018 1.904 4.21 4.21 0 0 1 .018-1.904Z" clip-rule="evenodd"/><circle cx="16.636" cy="22.171" r="1.241" fill="#996322"/><circle cx="22.841" cy="25.274" r="1.241" fill="#996322"/><mask id="e" width="23" height="6" x="10" y="29" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#D9D9D9" d="M10.5 29.4h21.7V35H10.5z"/></mask><g filter="url(#d)" mask="url(#e)"><ellipse cx="21.349" cy="29.633" fill="#D3A401" rx="7.233" ry="2.567"/></g><defs><filter id="a" width="67.667" height="67.667" x="-12.834" y="-12.833" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14655" stdDeviation="6.767"/></filter><filter id="d" width="20.067" height="10.733" x="11.316" y="24.267" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14655" stdDeviation="1.4"/></filter><linearGradient id="c" x1="20.706" x2="20.706" y1="11.665" y2="28.864" gradientUnits="userSpaceOnUse"><stop offset=".64" stop-color="#BD9301"/><stop offset="1" stop-color="#977601"/></linearGradient></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/images/gtmooc_cookie_dark.svg b/chrome/browser/resources/settings/images/gtmooc_cookie_dark.svg index 16dc1ce..0307fe37 100644 --- a/chrome/browser/resources/settings/images/gtmooc_cookie_dark.svg +++ b/chrome/browser/resources/settings/images/gtmooc_cookie_dark.svg
@@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="43" height="44" fill="none" viewBox="0 0 43 44"><mask id="b" width="42" height="36" x="1" y="2" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="42" height="35" x="1" y="2.8" fill="#146C2E" rx="17.5"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="42" height="35" x="1" y="2.8" fill="#146C2E" rx="17.5"/></g><g filter="url(#c)"><rect width="2.039" height="6.118" x="14.474" y="26.6" fill="#37BE5F" rx="1.02" transform="rotate(45 14.474 26.6)"/><rect width="4.2" height="13.3" x="11.804" y="27.74" fill="#37BE5F" rx="2.1" transform="rotate(45 11.804 27.74)"/><circle cx="22" cy="20.3" r="9.8" stroke="#6DD58C" stroke-width="1.4"/></g><circle cx="16.4" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="22" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="27.6" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="22" cy="20.3" r="7.7" fill="url(#d)"/><circle cx="36.7" cy="13.301" r="1.4" fill="#292A2D"/><circle cx="40.9" cy="13.301" r="1.4" fill="#292A2D"/><circle cx="3.1" cy="25.899" r="1.4" fill="#292A2D"/><circle cx="7.3" cy="25.899" r="1.4" fill="#292A2D"/><defs><filter id="a" width="70" height="63" x="-13" y="-11.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14651" stdDeviation="7"/></filter><filter id="c" width="34.831" height="35.044" x=".469" y="8.401" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1.4"/><feGaussianBlur stdDeviation="1.4"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_1540_14651"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_1540_14651" result="shape"/></filter><linearGradient id="d" x1="16.225" x2="26.492" y1="15.488" y2="25.433" gradientUnits="userSpaceOnUse"><stop stop-color="#37BE5F"/><stop offset=".71" stop-color="#198639" stop-opacity="0"/></linearGradient></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="none" viewBox="0 0 42 42"><mask id="b" width="42" height="42" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#EA8600" rx="11.503"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#EA8600" rx="11.503"/></g><path stroke="#292A2D" stroke-width="1.4" d="M15.615 7H7v8.615M26.385 7H35v8.615M15.615 35H7v-8.615M26.385 35H35v-8.615"/><path fill="url(#c)" fill-rule="evenodd" d="M23.698 15.344a.975.975 0 0 0-1.098-.458 4.195 4.195 0 0 1-4.956-2.272c-.186-.4-.654-.636-1.037-.417a9.13 9.13 0 1 0 12.587 12.216c.194-.363-.01-.797-.371-.993a4.194 4.194 0 0 1-2.045-4.787c.142-.523-.2-1.16-.716-1.329a4.207 4.207 0 0 1-2.364-1.96Z" clip-rule="evenodd"/><circle cx="16.636" cy="17.206" r="1.241" fill="#996322"/><circle cx="21.6" cy="19.689" r="1.241" fill="#996322"/><path fill="#996322" fill-rule="evenodd" d="M26.75 18.744a1.241 1.241 0 1 0-.018 1.904 4.21 4.21 0 0 1 .018-1.904Z" clip-rule="evenodd"/><circle cx="16.636" cy="22.171" r="1.241" fill="#996322"/><circle cx="22.841" cy="25.274" r="1.241" fill="#996322"/><mask id="e" width="23" height="6" x="10" y="29" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#D9D9D9" d="M10.5 29.4h21.7V35H10.5z"/></mask><g filter="url(#d)" mask="url(#e)"><ellipse cx="21.349" cy="29.633" fill="#996322" rx="7.233" ry="2.567"/></g><defs><filter id="a" width="67.667" height="67.667" x="-12.834" y="-12.833" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14654" stdDeviation="6.767"/></filter><filter id="d" width="20.067" height="10.733" x="11.316" y="24.267" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14654" stdDeviation="1.4"/></filter><linearGradient id="c" x1="20.536" x2="20.536" y1="11.831" y2="29.259" gradientUnits="userSpaceOnUse"><stop offset=".64" stop-color="#FBBC04"/><stop offset="1" stop-color="#977601"/></linearGradient></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/images/gtmooc_search.svg b/chrome/browser/resources/settings/images/gtmooc_search.svg index cfb2a881..a0eb893 100644 --- a/chrome/browser/resources/settings/images/gtmooc_search.svg +++ b/chrome/browser/resources/settings/images/gtmooc_search.svg
@@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="none" viewBox="0 0 42 42"><mask id="b" width="42" height="42" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#FCC934" rx="11.503"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#FCC934" rx="11.503"/></g><path stroke="#fff" stroke-width="1.4" d="M15.615 7H7v8.615M26.385 7H35v8.615M15.615 35H7v-8.615M26.385 35H35v-8.615"/><path fill="url(#c)" fill-rule="evenodd" d="M23.698 15.344a.975.975 0 0 0-1.098-.458 4.199 4.199 0 0 1-5.016-2.406c-.182-.433-.69-.69-1.084-.436a9.13 9.13 0 1 0 12.724 12.433c.225-.37.016-.835-.366-1.038a4.194 4.194 0 0 1-2.08-4.806c.142-.523-.2-1.16-.716-1.329a4.207 4.207 0 0 1-2.364-1.96Z" clip-rule="evenodd"/><circle cx="16.636" cy="17.206" r="1.241" fill="#996322"/><circle cx="21.6" cy="19.689" r="1.241" fill="#996322"/><path fill="#996322" fill-rule="evenodd" d="M26.75 18.744a1.241 1.241 0 1 0-.018 1.904 4.21 4.21 0 0 1 .018-1.904Z" clip-rule="evenodd"/><circle cx="16.636" cy="22.171" r="1.241" fill="#996322"/><circle cx="22.841" cy="25.274" r="1.241" fill="#996322"/><mask id="e" width="23" height="6" x="10" y="29" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#D9D9D9" d="M10.5 29.4h21.7V35H10.5z"/></mask><g filter="url(#d)" mask="url(#e)"><ellipse cx="21.349" cy="29.633" fill="#D3A401" rx="7.233" ry="2.567"/></g><defs><filter id="a" width="67.667" height="67.667" x="-12.834" y="-12.833" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14655" stdDeviation="6.767"/></filter><filter id="d" width="20.067" height="10.733" x="11.316" y="24.267" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14655" stdDeviation="1.4"/></filter><linearGradient id="c" x1="20.706" x2="20.706" y1="11.665" y2="28.864" gradientUnits="userSpaceOnUse"><stop offset=".64" stop-color="#BD9301"/><stop offset="1" stop-color="#977601"/></linearGradient></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="43" height="44" fill="none" viewBox="0 0 43 44"><mask id="b" width="42" height="36" x="1" y="2" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="42" height="35" x="1" y="2.8" fill="#6DD58C" rx="17.5"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="42" height="35" x="1" y="2.8" fill="#6DD58C" rx="17.5"/></g><g filter="url(#c)"><rect width="2.039" height="6.118" x="14.474" y="26.6" fill="#146C2E" rx="1.02" transform="rotate(45 14.474 26.6)"/><rect width="4.2" height="13.3" x="11.804" y="27.74" fill="#146C2E" rx="2.1" transform="rotate(45 11.804 27.74)"/><circle cx="22" cy="20.3" r="9.8" stroke="#198639" stroke-width="1.4"/></g><circle cx="16.4" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="22" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="27.6" cy="20.3" r="2.1" fill="#DCEEFF"/><circle cx="22" cy="20.3" r="7.7" fill="url(#d)"/><circle cx="36.7" cy="13.301" r="1.4" fill="#fff"/><circle cx="40.9" cy="13.301" r="1.4" fill="#fff"/><circle cx="3.1" cy="25.899" r="1.4" fill="#fff"/><circle cx="7.3" cy="25.899" r="1.4" fill="#fff"/><defs><filter id="a" width="70" height="63" x="-13" y="-11.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14652" stdDeviation="7"/></filter><filter id="c" width="34.831" height="35.044" x=".469" y="8.401" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1.4"/><feGaussianBlur stdDeviation="1.4"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_1540_14652"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_1540_14652" result="shape"/></filter><linearGradient id="d" x1="16.225" x2="26.492" y1="15.488" y2="25.433" gradientUnits="userSpaceOnUse"><stop stop-color="#37BE5F"/><stop offset=".71" stop-color="#198639" stop-opacity="0"/></linearGradient></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/images/gtmooc_search_dark.svg b/chrome/browser/resources/settings/images/gtmooc_search_dark.svg index 0307fe37..16dc1ce 100644 --- a/chrome/browser/resources/settings/images/gtmooc_search_dark.svg +++ b/chrome/browser/resources/settings/images/gtmooc_search_dark.svg
@@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" fill="none" viewBox="0 0 42 42"><mask id="b" width="42" height="42" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#EA8600" rx="11.503"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="40.6" height="40.6" x=".699" y=".7" fill="#EA8600" rx="11.503"/></g><path stroke="#292A2D" stroke-width="1.4" d="M15.615 7H7v8.615M26.385 7H35v8.615M15.615 35H7v-8.615M26.385 35H35v-8.615"/><path fill="url(#c)" fill-rule="evenodd" d="M23.698 15.344a.975.975 0 0 0-1.098-.458 4.195 4.195 0 0 1-4.956-2.272c-.186-.4-.654-.636-1.037-.417a9.13 9.13 0 1 0 12.587 12.216c.194-.363-.01-.797-.371-.993a4.194 4.194 0 0 1-2.045-4.787c.142-.523-.2-1.16-.716-1.329a4.207 4.207 0 0 1-2.364-1.96Z" clip-rule="evenodd"/><circle cx="16.636" cy="17.206" r="1.241" fill="#996322"/><circle cx="21.6" cy="19.689" r="1.241" fill="#996322"/><path fill="#996322" fill-rule="evenodd" d="M26.75 18.744a1.241 1.241 0 1 0-.018 1.904 4.21 4.21 0 0 1 .018-1.904Z" clip-rule="evenodd"/><circle cx="16.636" cy="22.171" r="1.241" fill="#996322"/><circle cx="22.841" cy="25.274" r="1.241" fill="#996322"/><mask id="e" width="23" height="6" x="10" y="29" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#D9D9D9" d="M10.5 29.4h21.7V35H10.5z"/></mask><g filter="url(#d)" mask="url(#e)"><ellipse cx="21.349" cy="29.633" fill="#996322" rx="7.233" ry="2.567"/></g><defs><filter id="a" width="67.667" height="67.667" x="-12.834" y="-12.833" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14654" stdDeviation="6.767"/></filter><filter id="d" width="20.067" height="10.733" x="11.316" y="24.267" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14654" stdDeviation="1.4"/></filter><linearGradient id="c" x1="20.536" x2="20.536" y1="11.831" y2="29.259" gradientUnits="userSpaceOnUse"><stop offset=".64" stop-color="#FBBC04"/><stop offset="1" stop-color="#977601"/></linearGradient></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" width="43" height="44" fill="none" viewBox="0 0 43 44"><mask id="b" width="42" height="36" x="1" y="2" maskUnits="userSpaceOnUse" style="mask-type:alpha"><rect width="42" height="35" x="1" y="2.8" fill="#146C2E" rx="17.5"/></mask><g filter="url(#a)" mask="url(#b)"><rect width="42" height="35" x="1" y="2.8" fill="#146C2E" rx="17.5"/></g><g filter="url(#c)"><rect width="2.039" height="6.118" x="14.474" y="26.6" fill="#37BE5F" rx="1.02" transform="rotate(45 14.474 26.6)"/><rect width="4.2" height="13.3" x="11.804" y="27.74" fill="#37BE5F" rx="2.1" transform="rotate(45 11.804 27.74)"/><circle cx="22" cy="20.3" r="9.8" stroke="#6DD58C" stroke-width="1.4"/></g><circle cx="16.4" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="22" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="27.6" cy="20.3" r="2.1" fill="#292A2D"/><circle cx="22" cy="20.3" r="7.7" fill="url(#d)"/><circle cx="36.7" cy="13.301" r="1.4" fill="#292A2D"/><circle cx="40.9" cy="13.301" r="1.4" fill="#292A2D"/><circle cx="3.1" cy="25.899" r="1.4" fill="#292A2D"/><circle cx="7.3" cy="25.899" r="1.4" fill="#292A2D"/><defs><filter id="a" width="70" height="63" x="-13" y="-11.2" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_1540_14651" stdDeviation="7"/></filter><filter id="c" width="34.831" height="35.044" x=".469" y="8.401" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="1.4"/><feGaussianBlur stdDeviation="1.4"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_1540_14651"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_1540_14651" result="shape"/></filter><linearGradient id="d" x1="16.225" x2="26.492" y1="15.488" y2="25.433" gradientUnits="userSpaceOnUse"><stop stop-color="#37BE5F"/><stop offset=".71" stop-color="#198639" stop-opacity="0"/></linearGradient></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/history_clusters/app.html b/chrome/browser/resources/side_panel/history_clusters/app.html index 6ca05f5..863f3bb 100644 --- a/chrome/browser/resources/side_panel/history_clusters/app.html +++ b/chrome/browser/resources/side_panel/history_clusters/app.html
@@ -6,28 +6,16 @@ } #searchbox { - margin: 16px auto 4px; - flex-shrink: 0; - } - - :host-context(html:not([chrome-refresh-2023])) #searchbox { - --cr-toolbar-field-max-width: calc(100% - 32px); - } - - :host-context([chrome-refresh-2023]) #searchbox { margin: var(--sp-body-padding); + flex-shrink: 0; width: auto; } - #historyClusters { + #historyClusters { flex: 1; - } - - :host-context([chrome-refresh-2023]) #historyClusters { margin-inline-start: var(--sp-body-padding); margin-bottom: var(--sp-body-padding); } - </style> <cr-toolbar-search-field id="searchbox" on-search-changed="onSearchChanged_" label="$i18n{historyClustersSearchPrompt}"
diff --git a/chrome/browser/resources/side_panel/history_clusters/history_clusters.html b/chrome/browser/resources/side_panel/history_clusters/history_clusters.html index 8ab1447..676505c1 100644 --- a/chrome/browser/resources/side_panel/history_clusters/history_clusters.html +++ b/chrome/browser/resources/side_panel/history_clusters/history_clusters.html
@@ -1,12 +1,10 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" - $i18n{chromeRefresh2023Attribute}> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <title>$i18n{historyClustersTabLabel}</title> <meta name="color-scheme" content="light dark"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> - <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome"> <style> html, @@ -18,18 +16,8 @@ } body { - background: white; - overflow: hidden; - } - - html[chrome-refresh-2023] body { background: var(--color-side-panel-content-background); - } - - @media (prefers-color-scheme: dark) { - body { - background: var(--google-grey-900); - } + overflow: hidden; } </style> <script type="module" src="app.js"></script>
diff --git a/chrome/browser/resources/side_panel/read_anything/BUILD.gn b/chrome/browser/resources/side_panel/read_anything/BUILD.gn index 8787f63..c9c4fb2a 100644 --- a/chrome/browser/resources/side_panel/read_anything/BUILD.gn +++ b/chrome/browser/resources/side_panel/read_anything/BUILD.gn
@@ -16,10 +16,14 @@ web_component_files = [ "app.ts", + "language_menu.ts", "read_anything_toolbar.ts", "voice_selection_menu.ts", ] - non_web_component_files = [ "common.ts" ] + non_web_component_files = [ + "common.ts", + "voice_language_util.ts", + ] icons_html_files = [ "icons.html" ] ts_composite = true
diff --git a/chrome/browser/resources/side_panel/read_anything/app.html b/chrome/browser/resources/side_panel/read_anything/app.html index 90a8412..3aa2cbf4 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.html +++ b/chrome/browser/resources/side_panel/read_anything/app.html
@@ -92,10 +92,12 @@ paused="[[speechPlayingState.paused]]" has-content="[[hasContent_]]" selected-voice="[[selectedVoice]]" + enabled-languages-in-pref="[[enabledLanguagesInPref]]" available-voices="[[availableVoices]]" preview-voice-playing="[[previewVoicePlaying]]" locale-to-display-name="[[localeToDisplayName]]" on-select-voice="onSelectVoice_" + on-voice-language-toggle="onVoiceLanguageToggle_" on-preview-voice="onPreviewVoice_" on-voice-menu-close="onVoiceMenuClose_" on-play-pause-click="onPlayPauseClick_"
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index 01f56e7..c2ec17e4 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -20,6 +20,8 @@ import {getTemplate} from './app.html.js'; import {validatedFontName} from './common.js'; import type {ReadAnythingToolbarElement} from './read_anything_toolbar.js'; +import type {VoicePackStatus} from './voice_language_util.js'; +import {mojoVoicePackStatusToVoicePackStatusEnum} from './voice_language_util.js'; const ReadAnythingElementBase = WebUiListenerMixin(PolymerElement); @@ -35,10 +37,6 @@ rate: number; } -interface VoicesByLanguage { - [lang: string]: SpeechSynthesisVoice[]; -} - // TODO(crbug.com/1465029): Remove colors defined here once the Views toolbar is // removed. const style = getComputedStyle(document.body); @@ -171,12 +169,6 @@ }; } -export enum VoicePackStatus { - NOT_INSTALLED, - INSTALLING, - INSTALLED, - ERROR, -} export enum PauseActionSource { DEFAULT, @@ -271,6 +263,7 @@ synth = window.speechSynthesis; private selectedVoice: SpeechSynthesisVoice|undefined; + private enabledLanguagesInPref: string[] = []; private availableVoices: SpeechSynthesisVoice[]; // If a preview is playing, this is set to the voice the preview is playing. @@ -756,19 +749,7 @@ if (!lang) { return; } - // The following possible values of "status" is a union of enum values of - // enum InstallationState and enum ErrorCode in read_anything.mojom - let voicePackStatus: VoicePackStatus; - if (status === 'kNotInstalled') { - voicePackStatus = VoicePackStatus.NOT_INSTALLED; - } else if (status === 'kInstalling') { - voicePackStatus = VoicePackStatus.INSTALLING; - } else if (status === 'kInstalled') { - voicePackStatus = VoicePackStatus.INSTALLED; - } else { - // TODO (b/331795122) Handle install errors on the UI - voicePackStatus = VoicePackStatus.ERROR; - } + const voicePackStatus = mojoVoicePackStatusToVoicePackStatusEnum(status); this.voicePackInstallStatus = {...this.voicePackInstallStatus, [lang]: voicePackStatus}; // TODO (b/335472298) Handle voice menu downloading voice spinners @@ -814,16 +795,6 @@ voicesForLanguage[0]; } - private getVoicesByLanguage(): VoicesByLanguage { - return this.getVoices().reduce( - (voicesByLang: VoicesByLanguage, voice: SpeechSynthesisVoice) => { - (voicesByLang[voice.lang] = voicesByLang[voice.lang] || []) - .push(voice); - return voicesByLang; - }, - {}); - } - private getVoices(refresh: boolean = false): SpeechSynthesisVoice[] { if (!this.availableVoices || refresh) { let availableVoices = this.synth.getVoices(); @@ -872,8 +843,13 @@ this.stopSpeech(PauseActionSource.VOICE_PREVIEW); - const defaultUtteranceSettings = this.defaultUtteranceSettings(); + // If there's no previewVoice, return after stopping the current preview + if (!event.detail) { + this.previewVoicePlaying = null; + return; + } + const defaultUtteranceSettings = this.defaultUtteranceSettings(); // TODO(crbug.com/1474951): Finalize the default voice preview text. const utterance = new SpeechSynthesisUtterance( loadTimeData.getString('readingModeVoicePreviewText')); @@ -1348,6 +1324,19 @@ this.resetSpeechPostSettingChange_(); } + private onVoiceLanguageToggle_(event: CustomEvent<{language: string}>) { + event.preventDefault(); + event.stopPropagation(); + const toggledLanguage = event.detail.language; + const currentlyEnabled = + this.enabledLanguagesInPref.includes(toggledLanguage); + this.enabledLanguagesInPref = currentlyEnabled ? + this.enabledLanguagesInPref.filter(lang => lang !== toggledLanguage) : + [...this.enabledLanguagesInPref, toggledLanguage]; + + chrome.readingMode.onLanguagePrefChange(toggledLanguage, !currentlyEnabled); + } + private resetSpeechPostSettingChange_() { // Don't call stopSpeech() if initAxPositionWithNode hasn't been called if (!this.speechPlayingState.speechStarted) { @@ -1436,6 +1425,7 @@ if (this.isReadAloudEnabled_) { this.updateSpeechRate_(chrome.readingMode.speechRate); this.selectPreferredVoice_(); + this.restoreEnabledLanguagesFromPref_(); } this.updateLineSpacing_(chrome.readingMode.lineSpacing); this.updateLetterSpacing_(chrome.readingMode.letterSpacing); @@ -1469,6 +1459,12 @@ this.$.toolbar.restoreSettingsFromPrefs(colorSuffix); } + private restoreEnabledLanguagesFromPref_() { + const storedLanguagesPref = chrome.readingMode.getLanguagesEnabledInPref(); + this.enabledLanguagesInPref = + storedLanguagesPref ? storedLanguagesPref : []; + } + private selectPreferredVoice_() { // TODO: b/40275871 - decide whether this is the behavior we want. This // shouldn't happen often, so just skip selecting a new voice for now. @@ -1484,12 +1480,9 @@ return; } - const selectedVoice = Object.entries(this.getVoicesByLanguage()) - .filter(([lang, _]) => lang) - .flatMap(([_, voices]) => voices) + const selectedVoice = this.getVoices() .filter(voice => voice.name === storedVoiceName); - assert(selectedVoice, 'Could not find stored selected voice'); this.selectedVoice = selectedVoice ? selectedVoice[0] : this.defaultVoice(); }
diff --git a/chrome/browser/resources/side_panel/read_anything/icons.html b/chrome/browser/resources/side_panel/read_anything/icons.html index ceff276..bdb1151 100644 --- a/chrome/browser/resources/side_panel/read_anything/icons.html +++ b/chrome/browser/resources/side_panel/read_anything/icons.html
@@ -105,9 +105,9 @@ d="M6.36667 10.85L10.85 8L6.36667 5.15V10.85ZM8 14.5333C7.1 14.5333 6.25 14.3667 5.45 14.0333C4.66111 13.6889 3.96667 13.2222 3.36667 12.6333C2.77778 12.0333 2.31111 11.3389 1.96667 10.55C1.63333 9.75 1.46667 8.9 1.46667 8C1.46667 7.08889 1.63333 6.23889 1.96667 5.45C2.31111 4.66111 2.77778 3.97222 3.36667 3.38333C3.96667 2.78333 4.66111 2.31667 5.45 1.98333C6.25 1.63889 7.1 1.46667 8 1.46667C8.91111 1.46667 9.76111 1.63889 10.55 1.98333C11.3389 2.31667 12.0278 2.78333 12.6167 3.38333C13.2167 3.97222 13.6833 4.66667 14.0167 5.46667C14.3611 6.25556 14.5333 7.1 14.5333 8C14.5333 8.9 14.3611 9.75 14.0167 10.55C13.6833 11.3389 13.2167 12.0333 12.6167 12.6333C12.0278 13.2222 11.3333 13.6889 10.5333 14.0333C9.74444 14.3667 8.9 14.5333 8 14.5333ZM8 13.15C9.43333 13.15 10.65 12.65 11.65 11.65C12.65 10.65 13.15 9.43333 13.15 8C13.15 6.56667 12.65 5.35 11.65 4.35C10.65 3.35 9.43333 2.85 8 2.85C6.56667 2.85 5.35 3.35 4.35 4.35C3.35 5.35 2.85 6.56667 2.85 8C2.85 9.43333 3.35 10.65 4.35 11.65C5.35 12.65 6.56667 13.15 8 13.15Z"> </path> </g> - <g id="pause-circle" viewBox="0 0 16 16"> + <g id="stop-circle" viewBox="0 0 16 16"> <path - d="M5.93333 10.4333H7.2V5.56667H5.93333V10.4333ZM8.8 10.4333H10.0667V5.56667H8.8V10.4333ZM8 14.5333C7.1 14.5333 6.25 14.3667 5.45 14.0333C4.66111 13.6889 3.96667 13.2222 3.36667 12.6333C2.77778 12.0333 2.31111 11.3389 1.96667 10.55C1.63333 9.75 1.46667 8.9 1.46667 8C1.46667 7.08889 1.63333 6.23889 1.96667 5.45C2.31111 4.66111 2.77778 3.97222 3.36667 3.38333C3.96667 2.78333 4.66111 2.31667 5.45 1.98333C6.25 1.63889 7.1 1.46667 8 1.46667C8.91111 1.46667 9.76111 1.63889 10.55 1.98333C11.3389 2.31667 12.0278 2.78333 12.6167 3.38333C13.2167 3.97222 13.6833 4.66667 14.0167 5.46667C14.3611 6.25556 14.5333 7.1 14.5333 8C14.5333 8.9 14.3611 9.75 14.0167 10.55C13.6833 11.3389 13.2167 12.0333 12.6167 12.6333C12.0278 13.2222 11.3333 13.6889 10.5333 14.0333C9.74444 14.3667 8.9 14.5333 8 14.5333ZM8 13.15C9.43333 13.15 10.65 12.65 11.65 11.65C12.65 10.65 13.15 9.43333 13.15 8C13.15 6.56667 12.65 5.35 11.65 4.35C10.65 3.35 9.43333 2.85 8 2.85C6.56667 2.85 5.35 3.35 4.35 4.35C3.35 5.35 2.85 6.56667 2.85 8C2.85 9.43333 3.35 10.65 4.35 11.65C5.35 12.65 6.56667 13.15 8 13.15Z"> + d="M5.56667 10.4333H10.4333V5.56667H5.56667V10.4333ZM8 14.5333C7.1 14.5333 6.25 14.3667 5.45 14.0333C4.66111 13.6889 3.96667 13.2222 3.36667 12.6333C2.77778 12.0333 2.31111 11.3389 1.96667 10.55C1.63333 9.75 1.46667 8.9 1.46667 8C1.46667 7.08889 1.63333 6.23889 1.96667 5.45C2.31111 4.66111 2.77778 3.97222 3.36667 3.38333C3.96667 2.78333 4.66111 2.31667 5.45 1.98333C6.25 1.63889 7.1 1.46667 8 1.46667C8.91111 1.46667 9.76111 1.63889 10.55 1.98333C11.3389 2.31667 12.0278 2.78333 12.6167 3.38333C13.2167 3.97222 13.6833 4.66667 14.0167 5.46667C14.3611 6.25556 14.5333 7.1 14.5333 8C14.5333 8.9 14.3611 9.75 14.0167 10.55C13.6833 11.3389 13.2167 12.0333 12.6167 12.6333C12.0278 13.2222 11.3333 13.6889 10.5333 14.0333C9.74444 14.3667 8.9 14.5333 8 14.5333ZM8 13.15C9.43333 13.15 10.65 12.65 11.65 11.65C12.65 10.65 13.15 9.43333 13.15 8C13.15 6.56667 12.65 5.35 11.65 4.35C10.65 3.35 9.43333 2.85 8 2.85C6.56667 2.85 5.35 3.35 4.35 4.35C3.35 5.35 2.85 6.56667 2.85 8C2.85 9.43333 3.35 10.65 4.35 11.65C5.35 12.65 6.56667 13.15 8 13.15Z" fill="#474747"> </path> </g> </defs>
diff --git a/chrome/browser/resources/side_panel/read_anything/language_menu.html b/chrome/browser/resources/side_panel/read_anything/language_menu.html new file mode 100644 index 0000000..8043e90 --- /dev/null +++ b/chrome/browser/resources/side_panel/read_anything/language_menu.html
@@ -0,0 +1,112 @@ +<style include="cr-hidden-style cr-icons"> + #languageMenu::part(dialog) { + min-width: 304px; + width: auto; + margin-left: var(--sp-body-padding); + margin-right: var(--sp-body-padding); + height: 60%; + } + + cr-icon { + --icon-size: 24px; + height: var(--icon-size); + width: var(--icon-size); + } + + .language-menu-title-bar { + display: flex; + width: 100%; + align-items: center; + justify-content: space-between; + } + + .language-menu-title { + float: left; + text-align: left; + font-size: 16px; + font-weight: 500; + display: table-cell; + vertical-align: middle; + } + + .language-menu-close-button { + float: right; + display: table-cell; + vertical-align: middle; + } + + .language-line { + display: flex; + align-items: center; + justify-content: space-between; + background-color: transparent; + border: none; + width: 100%; + color: var(--color-sys-on-surface-subtle); + } + + .dropdown-line { + height: 48px; + align-items: center; + } + + .language-name { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + font-size: 13px; + font-weight: 500; + padding-inline-end: 16px; + } + + .language-menu-body { + padding-bottom: 16px; + } + + .search-field { + padding: 0 var(--sp-body-padding) 0 var(--sp-body-padding); + } + + </style> + +<cr-dialog id="languageMenu" ignore-popstate> + <div slot="title" class="language-menu-title-bar"> + <div class="language-menu-title">$i18n{readingModeLanguageMenuTitle}</div> + <cr-icon-button id="close" class="action-icon language-menu-close-button" + iron-icon="cr:close" + on-click="closeLanguageMenu_" + aria-label="$i18n{readingModeLanguageMenuClose}"> + </cr-icon-button> + </div> + <div slot="header"> + <cr-input + class="search-field" + type="search" + placeholder="$i18n{readingModeLanguageMenuSearchLabel}" + value="{{languageSearchValue_}}"> + <cr-icon slot="inline-prefix" alt="" icon="cr:search"> + </cr-icon> + <cr-icon-button iron-icon="cr:clear" + hidden$="[[!languageSearchValue_]]" slot="inline-suffix" + on-click="onClearSearchClick_" + title="$i18n{readingModeLanguageMenuSearchClear}"> + </cr-icon-button> + </cr-input> + </div> + <div slot="body" class="language-menu-body"> + <!-- TODO(b/333785012): Add initial-counts to the dom-repeats here. --> + <template is="dom-repeat" + items="[[computeAvailableLanguages_(availableVoices, + localeToDisplayName, languageSearchValue_, + enabledLanguagesInPref)]]"> + <div class="language-line dropdown-line"> + <span class="language-name"> + [[item.language]] + </span> + <cr-toggle + checked="[[item.checked]]" + on-change="onToggleChange_"></cr-toggle> + </div> + </template> + </div> +</cr-dialog> \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/read_anything/language_menu.ts b/chrome/browser/resources/side_panel/read_anything/language_menu.ts new file mode 100644 index 0000000..067f19f --- /dev/null +++ b/chrome/browser/resources/side_panel/read_anything/language_menu.ts
@@ -0,0 +1,117 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/cr_elements/cr_hidden_style.css.js'; +import '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import '//resources/cr_elements/cr_icons.css.js'; +import '//resources/cr_elements/icons.html.js'; +import '//resources/cr_elements/cr_dialog/cr_dialog.js'; +import '//resources/cr_elements/cr_icons.css.js'; +import '//resources/cr_elements/cr_input/cr_input.js'; +import '//resources/cr_elements/cr_toggle/cr_toggle.js'; +import './icons.html.js'; + +import type {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.js'; +import {WebUiListenerMixin} from '//resources/cr_elements/web_ui_listener_mixin.js'; +import type {DomRepeatEvent} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './language_menu.html.js'; + +export interface LanguageMenuElement { + $: { + languageMenu: CrDialogElement, + }; +} + +interface LanguageDropdownItem { + language: string; + checked: boolean; + callback: () => void; +} + +const LanguageMenuElementBase = WebUiListenerMixin(PolymerElement); + +export const LANGUAGE_TOGGLE_EVENT = 'voice-language-toggle'; + +export class LanguageMenuElement extends LanguageMenuElementBase { + static get is() { + return 'language-menu'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + enabledLanguagesInPref: Array, + availableVoices: Array, + languageSearchValue_: String, + localeToDisplayName: Object, + }; + } + + private languageSearchValue_: string; + + private closeLanguageMenu_() { + this.$.languageMenu.close(); + } + + private onClearSearchClick_() { + this.languageSearchValue_ = ''; + } + + private onToggleChange_(event: DomRepeatEvent<LanguageDropdownItem>) { + event.model.item.callback(); + } + + private computeAvailableLanguages_( + availableVoices: SpeechSynthesisVoice[], + localeToDisplayName: {[lang: string]: string}, + languageSearchValue: string|undefined, + enabledLanguagesInPref: string[]): LanguageDropdownItem[] { + if (!availableVoices) { + return []; + } + const allLanguages = availableVoices.map( + voice => (localeToDisplayName && voice.lang in localeToDisplayName) ? + localeToDisplayName[voice.lang] : + voice.lang); + return [...new Set(allLanguages)] + .filter(lang => { + if (languageSearchValue) { + return lang.toLowerCase().includes( + languageSearchValue.toLowerCase()); + } else { + return true; + } + }) + .map(lang => ({ + language: lang, + checked: enabledLanguagesInPref && + enabledLanguagesInPref.includes(lang), + callback: () => + this.dispatchEvent(new CustomEvent(LANGUAGE_TOGGLE_EVENT, { + bubbles: true, + composed: true, + detail: { + language: lang, + }, + })), + })); + } + + showDialog() { + this.$.languageMenu.showModal(); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'language-menu': LanguageMenuElement; + } +} + +customElements.define(LanguageMenuElement.is, LanguageMenuElement);
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts index 2c6014d..b82a416f9 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_anything.d.ts
@@ -76,6 +76,9 @@ // Returns the stored user voice preference for the current language function getStoredVoice(): string; + // Returns the stored user preference for enabled languages. + function getLanguagesEnabledInPref(): string[]; + // Returns a list of AXNodeIDs corresponding to the unignored children of // the AXNode for the provided AXNodeID. If there is a selection contained // in this node, only returns children which are partially or entirely @@ -163,6 +166,10 @@ // Called when the voice used for speech is changed via the webui toolbar. function onVoiceChange(voice: string, lang: string): void; + // Called when a language is enabled/disabled for via the webui language + // menu. + function onLanguagePrefChange(lang: string, enabled: boolean): void; + // Called when the highlight granularity is changed via the webui toolbar. function turnedHighlightOn(): void; function turnedHighlightOff(): void;
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.html b/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.html index f45799ee..2b7951d 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.html +++ b/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.html
@@ -110,7 +110,7 @@ class="toolbar-button audio-controls" id="play-pause" disabled="[[!hasContent]]" - title$="[[playPauseButtonAriaLabel_(paused)]]" + title$="[[playPauseButtonTitle_(paused)]]" aria-label$="[[playPauseButtonAriaLabel_(paused)]]" aria-keyshortcuts="k" aria-description="$i18n{playDescription}" @@ -163,6 +163,7 @@ id="voiceSelectionMenu" selected-voice="[[selectedVoice]]" available-voices="[[availableVoices]]" + enabled-languages-in-pref="[[enabledLanguagesInPref]]" locale-to-display-name="[[localeToDisplayName]]" paused="[[paused]]" preview-voice-playing="[[previewVoicePlaying]]">
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.ts b/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.ts index ce05aebc..f0055cd 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_anything_toolbar.ts
@@ -128,6 +128,7 @@ hasContent: Boolean, selectedVoice: Object, availableVoices: Array, + enabledLanguagesInPref: Array, localeToDisplayName: Object, previewVoicePlaying: Object, areFontsLoaded_: Boolean, @@ -557,6 +558,11 @@ loadTimeData.getString('pauseLabel'); } + private playPauseButtonTitle_(paused: boolean) { + return paused ? loadTimeData.getString('playTooltip') : + loadTimeData.getString('pauseTooltip'); + } + private playPauseButtonIronIcon_(paused: boolean) { return paused ? 'read-anything-20:play' : 'read-anything-20:pause'; }
diff --git a/chrome/browser/resources/side_panel/read_anything/voice_language_util.ts b/chrome/browser/resources/side_panel/read_anything/voice_language_util.ts new file mode 100644 index 0000000..de5e71d5 --- /dev/null +++ b/chrome/browser/resources/side_panel/read_anything/voice_language_util.ts
@@ -0,0 +1,26 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export enum VoicePackStatus { + NOT_INSTALLED, + INSTALLING, + INSTALLED, + ERROR, +} + +// The following possible values of "status" is a union of enum values of +// enum InstallationState and enum ErrorCode in read_anything.mojom +export function mojoVoicePackStatusToVoicePackStatusEnum( + mojoPackStatus: string) { + if (mojoPackStatus === 'kNotInstalled') { + return VoicePackStatus.NOT_INSTALLED; + } else if (mojoPackStatus === 'kInstalling') { + return VoicePackStatus.INSTALLING; + } else if (mojoPackStatus === 'kInstalled') { + return VoicePackStatus.INSTALLED; + } + // The success statuses were not sent so return an Error + // TODO (b/331795122) Handle install errors on the UI + return VoicePackStatus.ERROR; +}
diff --git a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.html b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.html index 5689401..1d1c71b2 100644 --- a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.html +++ b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.html
@@ -69,6 +69,19 @@ .item-invisible-true { visibility: hidden; } + .menu-divider { + border-top: 1px solid var(--cr-active-background-color); + } + .language-menu-button { + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + font-size: 13px; + font-weight: 500; + margin-bottom: 3px; + height: 24px; + } + </style> <!-- TODO(b/333785012): Add initial-counts to the dom-repeats here. --> @@ -103,6 +116,27 @@ </template> </div> </template> + + <hr class="menu-divider"> + + <div> + <button + class="dropdown-item + dropdown-voice-selection-button language-menu-button" + on-click="openLanguageMenu_"> + $i18n{readingModeLanguageMenu} + </button> + </div> </cr-action-menu> </template> </cr-lazy-render> + +<cr-lazy-render id="languageMenu"> + <template> + <language-menu + enabled-languages-in-pref="[[enabledLanguagesInPref]]" + locale-to-display-name="[[localeToDisplayName]]" + available-voices="[[availableVoices]]"></language-menu> + </language-menu> + </template> +</cr-lazy-render> \ No newline at end of file
diff --git a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts index 442066e6..71a9631 100644 --- a/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts +++ b/chrome/browser/resources/side_panel/read_anything/voice_selection_menu.ts
@@ -8,6 +8,7 @@ import '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; import '//resources/cr_elements/cr_lazy_render/cr_lazy_render.js'; import './icons.html.js'; +import './language_menu.js'; import type {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; import {AnchorAlignment} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; @@ -18,11 +19,13 @@ import type {DomRepeatEvent} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import type {LanguageMenuElement} from './language_menu.js'; import {getTemplate} from './voice_selection_menu.html.js'; export interface VoiceSelectionMenuElement { $: { voiceSelectionMenu: CrLazyRenderElement<CrActionMenuElement>, + languageMenu: CrLazyRenderElement<LanguageMenuElement>, }; } @@ -41,6 +44,9 @@ id: string; } +// Events emitted from the voice selection menu to the app +export const PLAY_PREVIEW_EVENT = 'preview-voice'; + // This string is not localized and will be in English, even for non-English // Natural voices. const NATURAL_STRING_IDENTIFIER = '(Natural)'; @@ -66,6 +72,7 @@ return { selectedVoice: Object, availableVoices: Array, + enabledLanguagesInPref: Array, previewVoicePlaying: Object, paused: Boolean, localeToDisplayName: Object, @@ -153,19 +160,18 @@ // line is to make sure that the voice-selection callback is not triggered. event.stopImmediatePropagation(); - const button = event.target as HTMLElement; - assert(button, 'no target for preview'); + const previewVoice = event.model.item.voice; + this.dispatchEvent(new CustomEvent(PLAY_PREVIEW_EVENT, { + bubbles: true, + composed: true, + detail: event.model.item.previewPlaying ? null + : { previewVoice }, + })); + } - if (!event.model.item.previewPlaying) { - const previewVoice = event.model.item.voice; - this.dispatchEvent(new CustomEvent('preview-voice', { - bubbles: true, - composed: true, - detail: { - previewVoice, - }, - })); - } + private openLanguageMenu_() { + this.$.voiceSelectionMenu.get().close(); + this.$.languageMenu.get().showDialog(); } private onClose_() { @@ -225,7 +231,7 @@ nameSuffix = ' ' + voiceName; } if (previewPlaying) { - return loadTimeData.getString('pauseLabel') + nameSuffix; + return loadTimeData.getString('stopLabel') + nameSuffix; } else { return loadTimeData.getString('playLabel') + nameSuffix; } @@ -233,7 +239,7 @@ private previewIcon_(previewPlaying: boolean): string { if (previewPlaying) { - return 'read-anything-20:pause-circle'; + return 'read-anything-20:stop-circle'; } else { return 'read-anything-20:play-circle'; }
diff --git a/chrome/browser/resources/side_panel/reading_list/BUILD.gn b/chrome/browser/resources/side_panel/reading_list/BUILD.gn index 485ded9..504b7ee 100644 --- a/chrome/browser/resources/side_panel/reading_list/BUILD.gn +++ b/chrome/browser/resources/side_panel/reading_list/BUILD.gn
@@ -16,19 +16,22 @@ ] web_component_files = [ - "app.ts", + "reading_list_app.ts", "reading_list_item.ts", ] non_web_component_files = [ "reading_list_api_proxy.ts" ] + css_files = [ "reading_list_item.css" ] icons_html_files = [ "icons.html" ] mojo_files_deps = [ "//chrome/browser/ui/webui/side_panel/reading_list:mojo_bindings_ts__generator" ] mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/side_panel/reading_list/reading_list.mojom-webui.ts" ] + html_to_wrapper_template = "detect" ts_composite = true ts_deps = [ + "//third_party/lit/v3_0:build_ts", "//third_party/polymer/v3_0:library", "//ui/webui/resources/cr_components/color_change_listener:build_ts", "//ui/webui/resources/cr_components/help_bubble:build_ts",
diff --git a/chrome/browser/resources/side_panel/reading_list/reading_list.html b/chrome/browser/resources/side_panel/reading_list/reading_list.html index 4e2c3fd1..64287dce 100644 --- a/chrome/browser/resources/side_panel/reading_list/reading_list.html +++ b/chrome/browser/resources/side_panel/reading_list/reading_list.html
@@ -16,7 +16,7 @@ </head> <body> <reading-list-app></reading-list-app> - <script type="module" src="app.js"></script> + <script type="module" src="reading_list_app.js"></script> <script type="module" src="chrome://resources/cr_elements/mwb_shared_vars.css.js"> </script> </body>
diff --git a/chrome/browser/resources/side_panel/reading_list/app.html b/chrome/browser/resources/side_panel/reading_list/reading_list_app.html similarity index 100% rename from chrome/browser/resources/side_panel/reading_list/app.html rename to chrome/browser/resources/side_panel/reading_list/reading_list_app.html
diff --git a/chrome/browser/resources/side_panel/reading_list/app.ts b/chrome/browser/resources/side_panel/reading_list/reading_list_app.ts similarity index 99% rename from chrome/browser/resources/side_panel/reading_list/app.ts rename to chrome/browser/resources/side_panel/reading_list/reading_list_app.ts index 59982eea..4f12b20 100644 --- a/chrome/browser/resources/side_panel/reading_list/app.ts +++ b/chrome/browser/resources/side_panel/reading_list/reading_list_app.ts
@@ -28,7 +28,7 @@ import type {DomRepeat} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {getTemplate} from './app.html.js'; +import {getTemplate} from './reading_list_app.html.js'; import type {ReadLaterEntriesByStatus, ReadLaterEntry} from './reading_list.mojom-webui.js'; import {CurrentPageActionButtonState} from './reading_list.mojom-webui.js'; import type {ReadingListApiProxy} from './reading_list_api_proxy.js';
diff --git a/chrome/browser/resources/side_panel/reading_list/reading_list_item.css b/chrome/browser/resources/side_panel/reading_list/reading_list_item.css new file mode 100644 index 0000000..1b1b71a --- /dev/null +++ b/chrome/browser/resources/side_panel/reading_list/reading_list_item.css
@@ -0,0 +1,13 @@ +/* Copyright 2024 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #scheme=relative + * #css_wrapper_metadata_end */ + +:host-context([dir='rtl']) #updateStatusButton { + /* Prevent checkmark from flipping in RTL. */ + transform: none; +}
diff --git a/chrome/browser/resources/side_panel/reading_list/reading_list_item.html b/chrome/browser/resources/side_panel/reading_list/reading_list_item.html index 96df5ba..cf3b22d 100644 --- a/chrome/browser/resources/side_panel/reading_list/reading_list_item.html +++ b/chrome/browser/resources/side_panel/reading_list/reading_list_item.html
@@ -1,29 +1,22 @@ -<style> - :host-context([dir='rtl']) #updateStatusButton { - /* Prevent checkmark from flipping in RTL. */ - transform: none; - } -</style> - <cr-url-list-item id="crUrlListItem" - title="[[data.title]]" - description="[[data.displayUrl]]" + title="${this.data.title}" + description="${this.data.displayUrl}" reverse-elide-description - description-meta="[[data.displayTimeSinceUpdate]]" - url="[[data.url.url]]"> + description-meta="${this.data.displayTimeSinceUpdate}" + url="${this.data.url.url}"> <cr-icon-button slot="suffix" id="updateStatusButton" disable-ripple - aria-label="[[getUpdateStatusButtonTooltip_('$i18n{tooltipMarkAsUnread}', - '$i18n{tooltipMarkAsRead}', data.read)]]" - iron-icon="[[getUpdateStatusButtonIcon_('cr:check-circle', - 'read-later:check-circle-outline', data.read)]]" - noink="[[!buttonRipples]]" no-ripple-on-focus - on-click="onUpdateStatusClick_" - title="[[getUpdateStatusButtonTooltip_('$i18n{tooltipMarkAsUnread}', - '$i18n{tooltipMarkAsRead}', data.read)]]"> + aria-label="${this.getUpdateStatusButtonTooltip_( + '$i18n{tooltipMarkAsUnread}', '$i18n{tooltipMarkAsRead}')}" + iron-icon="${this.getUpdateStatusButtonIcon_('cr:check-circle', + 'read-later:check-circle-outline')}" + ?noink="${!this.buttonRipples}" no-ripple-on-focus + @click="${this.onUpdateStatusClick_}" + title="${this.getUpdateStatusButtonTooltip_('$i18n{tooltipMarkAsUnread}', + '$i18n{tooltipMarkAsRead}')}"> </cr-icon-button> <cr-icon-button slot="suffix" id="deleteButton" aria-label="$i18n{tooltipDelete}" - iron-icon="cr:close" noink="[[!buttonRipples]]" no-ripple-on-focus - on-click="onItemDeleteClick_" title="$i18n{tooltipDelete}"> + iron-icon="cr:close" ?noink="${!this.buttonRipples}" no-ripple-on-focus + @click="${this.onItemDeleteClick_}" title="$i18n{tooltipDelete}"> </cr-icon-button> </cr-url-list-item>
diff --git a/chrome/browser/resources/side_panel/reading_list/reading_list_item.ts b/chrome/browser/resources/side_panel/reading_list/reading_list_item.ts index ce3a7ca8..fb412c2 100644 --- a/chrome/browser/resources/side_panel/reading_list/reading_list_item.ts +++ b/chrome/browser/resources/side_panel/reading_list/reading_list_item.ts
@@ -4,22 +4,19 @@ import 'chrome://resources/cr_elements/cr_url_list_item/cr_url_list_item.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import 'chrome://resources/cr_elements/cr_icons.css.js'; import 'chrome://resources/cr_elements/icons.html.js'; -import 'chrome://resources/cr_elements/mwb_element_shared_style.css.js'; -import 'chrome://resources/cr_elements/mwb_shared_vars.css.js'; -import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import './icons.html.js'; import type {CrUrlListItemElement} from 'chrome://resources/cr_elements/cr_url_list_item/cr_url_list_item.js'; -import {MouseHoverableMixin} from 'chrome://resources/cr_elements/mouse_hoverable_mixin.js'; +import {MouseHoverableMixinLit} from 'chrome://resources/cr_elements/mouse_hoverable_mixin_lit.js'; import {assertNotReached} from 'chrome://resources/js/assert.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {ReadLaterEntry} from './reading_list.mojom-webui.js'; import type {ReadingListApiProxy} from './reading_list_api_proxy.js'; import {ReadingListApiProxyImpl} from './reading_list_api_proxy.js'; -import {getTemplate} from './reading_list_item.html.js'; +import {getCss} from './reading_list_item.css.js'; +import {getHtml} from './reading_list_item.html.js'; export const MARKED_AS_READ_UI_EVENT = 'reading-list-marked-as-read'; @@ -34,25 +31,25 @@ }; } -const ReadingListItemElementBase = MouseHoverableMixin(PolymerElement); +const ReadingListItemElementBase = MouseHoverableMixinLit(CrLitElement); export class ReadingListItemElement extends ReadingListItemElementBase { static get is() { return 'reading-list-item'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - data: Object, - buttonRipples: Boolean, - title: { - computed: 'computeTitle_(data.title)', - reflectToAttribute: true, - }, + data: {type: Object}, + buttonRipples: {type: Boolean}, }; } @@ -61,18 +58,13 @@ private apiProxy_: ReadingListApiProxy = ReadingListApiProxyImpl.getInstance(); - override ready() { - super.ready(); + override firstUpdated() { this.addEventListener('click', this.onClick_); this.addEventListener('auxclick', this.onAuxClick_.bind(this)); this.addEventListener('contextmenu', this.onContextMenu_.bind(this)); this.addEventListener('keydown', this.onKeyDown_.bind(this)); } - private computeTitle_(): string { - return this.data.title; - } - override focus() { this.$.crUrlListItem.focus(); } @@ -145,7 +137,7 @@ e.stopPropagation(); } - private onUpdateStatusClick_(e: Event) { + protected onUpdateStatusClick_(e: Event) { e.stopPropagation(); this.apiProxy_.updateReadStatus(this.data.url, !this.data.read); if (!this.data.read) { @@ -154,7 +146,7 @@ } } - private onItemDeleteClick_(e: Event) { + protected onItemDeleteClick_(e: Event) { e.stopPropagation(); this.apiProxy_.removeEntry(this.data.url); } @@ -162,7 +154,7 @@ /** * @return The appropriate icon for the current state */ - private getUpdateStatusButtonIcon_( + protected getUpdateStatusButtonIcon_( markAsUnreadIcon: string, markAsReadIcon: string): string { return this.data.read ? markAsUnreadIcon : markAsReadIcon; } @@ -170,7 +162,7 @@ /** * @return The appropriate tooltip for the current state */ - private getUpdateStatusButtonTooltip_( + protected getUpdateStatusButtonTooltip_( markAsUnreadTooltip: string, markAsReadTooltip: string): string { return this.data.read ? markAsUnreadTooltip : markAsReadTooltip; }
diff --git a/chrome/browser/resources/tab_search/tab_organization_new_badge.html b/chrome/browser/resources/tab_search/tab_organization_new_badge.html index 05752f17..95e88e5 100644 --- a/chrome/browser/resources/tab_search/tab_organization_new_badge.html +++ b/chrome/browser/resources/tab_search/tab_organization_new_badge.html
@@ -1,11 +1,8 @@ <style include="mwb-shared-style"> - .chip { - background-color: var(--color-tab-search-divider); - border-radius: 4px; + .text { font-size: 9px; - font-weight: 700; + font-weight: 500; line-height: 9px; - padding: 4px; text-wrap: nowrap; } @@ -25,6 +22,6 @@ </style> <div class="row"> - <div class="chip">$i18n{newTabs}</div> + <div class="text">$i18n{newTabs}</div> <div class="divider"></div> </div>
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc index abb3f0c..7ec41a8f 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc
@@ -198,6 +198,13 @@ return request.per_profile_request(); } +bool IgnoreErrorResultForResumableUpload(BinaryUploadService::Request* request, + BinaryUploadService::Result result) { + return IsResumableUpload(*request) && + (result == BinaryUploadService::Result::FILE_TOO_LARGE || + result == BinaryUploadService::Result::FILE_ENCRYPTED); +} + } // namespace // static @@ -500,9 +507,16 @@ } if (result != Result::SUCCESS) { - FinishRequest(request, result, - enterprise_connectors::ContentAnalysisResponse()); - return; + if (!IgnoreErrorResultForResumableUpload(request, result)) { + FinishRequest(request, result, + enterprise_connectors::ContentAnalysisResponse()); + return; + } + + // If the error is not unrecoverable, chrome can attempt to sent the + // file contents to the content analysis service. Let the service know that + // a metadata-only analysis is required. + request->set_require_metadata_verdict(true); } if (!request->IsAuthRequest() && data.size == 0) { @@ -534,8 +548,9 @@ upload_request = IsResumableUpload(*request) ? ResumableUploadRequest::CreateFileRequest( - url_loader_factory_, std::move(url), metadata, data.path, - data.size, std::move(traffic_annotation), std::move(callback)) + url_loader_factory_, std::move(url), metadata, result, + data.path, data.size, std::move(traffic_annotation), + std::move(callback)) : MultipartUploadRequest::CreateFileRequest( url_loader_factory_, std::move(url), metadata, data.path, data.size, std::move(traffic_annotation), @@ -545,7 +560,7 @@ upload_request = IsResumableUpload(*request) ? ResumableUploadRequest::CreatePageRequest( - url_loader_factory_, std::move(url), metadata, + url_loader_factory_, std::move(url), metadata, result, std::move(data.page), std::move(traffic_annotation), std::move(callback)) : MultipartUploadRequest::CreatePageRequest(
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc index 6eb907a..2142117 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/command_line.h" +#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" @@ -120,6 +121,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -132,6 +134,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ConnectorUploadRequest::Callback callback) override { @@ -318,13 +321,26 @@ BinaryUploadService::Result scanning_result; enterprise_connectors::ContentAnalysisResponse scanning_response; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc"); + ASSERT_TRUE(base::WriteFile(file_path, "test")); + + ExpectNetworkResponse(/*should_succeed=*/false, + enterprise_connectors::ContentAnalysisResponse()); ExpectInstanceID("valid id"); + std::unique_ptr<MockRequest> request = MakeRequest( &scanning_result, &scanning_response, /*is_advanced_protection*/ false); + request->set_analysis_connector( + enterprise_connectors::AnalysisConnector::FILE_ATTACHED); ON_CALL(*request, GetRequestData(_)) - .WillByDefault( - Invoke([](BinaryUploadService::Request::DataCallback callback) { + .WillByDefault(Invoke( + [file_path](BinaryUploadService::Request::DataCallback callback) { BinaryUploadService::Request::Data data; + data.path = file_path; + data.size = 4; // Must not be zero. std::move(callback).Run(BinaryUploadService::Result::FILE_TOO_LARGE, std::move(data)); })); @@ -332,7 +348,9 @@ content::RunAllTasksUntilIdle(); - EXPECT_EQ(scanning_result, BinaryUploadService::Result::FILE_TOO_LARGE); + EXPECT_EQ(scanning_result, is_resumable_upload_enabled() + ? BinaryUploadService::Result::UPLOAD_FAILURE + : BinaryUploadService::Result::FILE_TOO_LARGE); } TEST_P(CloudBinaryUploadServiceTest, FailsWhenMissingInstanceID) {
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h b/chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h index aa0f17ca..ed551a0 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h
@@ -9,6 +9,7 @@ #include "base/functional/callback.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/scoped_refptr.h" +#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/connector_data_pipe_getter.h" #include "components/file_access/scoped_file_access.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -141,6 +142,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -149,6 +151,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ConnectorUploadRequest::Callback callback) = 0;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc index ba083cb..bae566c 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
@@ -364,8 +364,12 @@ traffic_annotation, std::move(callback)); } + // Note that multipart uploads only handle data that is less than + // `kMaxUploadSizeBytes` and not encrypted. Therefore `Result::SUCCESS` is + // passed as the `get_data_result` argument. return factory_->CreateFileRequest(url_loader_factory, base_url, metadata, - path, file_size, traffic_annotation, + BinaryUploadService::Result::SUCCESS, path, + file_size, traffic_annotation, std::move(callback)); } @@ -385,6 +389,7 @@ } return factory_->CreatePageRequest(url_loader_factory, base_url, metadata, + BinaryUploadService::Result::SUCCESS, std::move(page_region), traffic_annotation, std::move(callback)); }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h index 01f33ad..071e24b 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h
@@ -25,8 +25,6 @@ // multipart protocol. This class is neither movable nor copyable. class MultipartUploadRequest : public ConnectorUploadRequest { public: - using Callback = ConnectorUploadRequest::Callback; - // Creates a MultipartUploadRequest, which will upload `data` to the given // `base_url` with `metadata` attached. MultipartUploadRequest(
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc index 72aa9b3..d69e99d 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc
@@ -59,6 +59,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -69,7 +70,8 @@ path, file_size, traffic_annotation, - std::move(callback)) { + std::move(callback)), + get_data_result_(get_data_result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } @@ -77,6 +79,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, Callback callback) @@ -85,7 +88,8 @@ metadata, std::move(page_region), traffic_annotation, - std::move(callback)) { + std::move(callback)), + get_data_result_(get_data_result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } @@ -139,19 +143,20 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, ResumableUploadRequest::Callback callback) { if (!factory_) { return std::make_unique<ResumableUploadRequest>( - url_loader_factory, base_url, metadata, path, file_size, - traffic_annotation, std::move(callback)); + url_loader_factory, base_url, metadata, get_data_result, path, + file_size, traffic_annotation, std::move(callback)); } return factory_->CreateFileRequest(url_loader_factory, base_url, metadata, - path, file_size, traffic_annotation, - std::move(callback)); + get_data_result, path, file_size, + traffic_annotation, std::move(callback)); } // static @@ -160,18 +165,19 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ResumableUploadRequest::Callback callback) { if (!factory_) { return std::make_unique<ResumableUploadRequest>( - url_loader_factory, base_url, metadata, std::move(page_region), - traffic_annotation, std::move(callback)); + url_loader_factory, base_url, metadata, get_data_result, + std::move(page_region), traffic_annotation, std::move(callback)); } return factory_->CreatePageRequest(url_loader_factory, base_url, metadata, - std::move(page_region), traffic_annotation, - std::move(callback)); + get_data_result, std::move(page_region), + traffic_annotation, std::move(callback)); } void ResumableUploadRequest::SendMetadataRequest() { @@ -210,12 +216,22 @@ return; } + // If there is an error or if the metadata check has already determined a + // verdict, CanUploadContent() returns false. response_code = url_loader_->ResponseInfo()->headers->response_code(); if (!CanUploadContent(url_loader_->ResponseInfo()->headers)) { Finish(url_loader_->NetError(), response_code, std::move(response_body)); return; } + // If chrome is being told to upload the content but the content is too large + // or is encrypted, fail now. + if (get_data_result_ == BinaryUploadService::Result::FILE_TOO_LARGE || + get_data_result_ == BinaryUploadService::Result::FILE_ENCRYPTED) { + Finish(net::ERR_FAILED, net::HTTP_BAD_REQUEST, std::move(response_body)); + return; + } + SendContentSoon(); }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h index 147e974..78d41d6 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h
@@ -14,6 +14,7 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" @@ -30,15 +31,18 @@ // resumable protocol. This class is neither movable nor copyable. class ResumableUploadRequest : public ConnectorUploadRequest { public: - using Callback = ConnectorUploadRequest::Callback; - // Creates a ResumableUploadRequest, which will upload the `metadata` of the // file corresponding to the provided `path` to the given `base_url`, and then // the file content to the `path` if necessary. + // + // `get_data_result` is the result when getting basic information about the + // file or page. It lets the ResumableUploadRequest know if the data is + // considered too large or is encrypted. ResumableUploadRequest( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -51,6 +55,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, Callback callback); @@ -66,6 +71,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& file, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -75,6 +81,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ResumableUploadRequest::Callback callback); @@ -131,6 +138,10 @@ // Helper used by metrics logging code. std::string GetRequestType(); + // The result returned by BinaryUploadService::Request::GetRequestData() when + // retrieving the data. + BinaryUploadService::Result get_data_result_; + // Retrieved from metadata response to be used in upload content to the // server. std::string upload_url_;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc index f885840..272e00e 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc
@@ -14,6 +14,7 @@ #include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "chrome/browser/enterprise/connectors/test/uploader_test_utils.h" +#include "chrome/browser/safe_browsing/cloud_content_scanning/connector_upload_request.h" #include "content/public/test/browser_task_environment.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/resource_request.h" @@ -35,10 +36,12 @@ MockResumableUploadRequest( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const base::FilePath& path, + BinaryUploadService::Result get_data_result, ResumableUploadRequest::Callback callback) : ResumableUploadRequest(url_loader_factory, GURL("https://google.com"), "metadata", + get_data_result, path, 123, TRAFFIC_ANNOTATION_FOR_TESTS, @@ -47,10 +50,12 @@ MockResumableUploadRequest( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, base::ReadOnlySharedMemoryRegion page_region, + BinaryUploadService::Result get_data_result, ResumableUploadRequest::Callback callback) : ResumableUploadRequest(url_loader_factory, GURL("https://google.com"), "metadata", + get_data_result, std::move(page_region), TRAFFIC_ANNOTATION_FOR_TESTS, std::move(callback)) {} @@ -84,24 +89,26 @@ std::unique_ptr<MockResumableUploadRequest> CreateFileRequest( const std::string& content, + BinaryUploadService::Result get_data_result, base::OnceCallback<void(bool success, int http_status, const std::string& response_data)> callback) { return std::make_unique<MockResumableUploadRequest>( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_), - CreateFile("text.txt", content), std::move(callback)); + CreateFile("text.txt", content), get_data_result, std::move(callback)); } std::unique_ptr<MockResumableUploadRequest> CreatePageRequest( const std::string& content, + BinaryUploadService::Result get_data_result, base::OnceCallback<void(bool success, int http_status, const std::string& response_data)> callback) { return std::make_unique<MockResumableUploadRequest>( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_), - CreatePage(content), std::move(callback)); + CreatePage(content), get_data_result, std::move(callback)); } void VerifyMetadataRequestHeaders( @@ -142,8 +149,35 @@ GeneratesCorrectMetadataHeaders_FileRequest) { network::ResourceRequest resource_request; auto connector_request = ResumableUploadRequest::CreateFileRequest( - nullptr, GURL(), "metadata", CreateFile("my_file_name.foo", "file_data"), - 9, TRAFFIC_ANNOTATION_FOR_TESTS, base::DoNothing()); + nullptr, GURL(), "metadata", BinaryUploadService::Result::SUCCESS, + CreateFile("my_file_name.foo", "file_data"), 9, + TRAFFIC_ANNOTATION_FOR_TESTS, base::DoNothing()); + auto* request = static_cast<ResumableUploadRequest*>(connector_request.get()); + request->SetMetadataRequestHeaders(&resource_request); + + VerifyMetadataRequestHeaders(std::move(resource_request), "9"); +} + +TEST_F(ResumableUploadRequestTest, + GeneratesCorrectMetadataHeaders_FileRequest_TooLarge) { + network::ResourceRequest resource_request; + auto connector_request = ResumableUploadRequest::CreateFileRequest( + nullptr, GURL(), "metadata", BinaryUploadService::Result::FILE_TOO_LARGE, + CreateFile("my_file_name.foo", "file_data"), 9, + TRAFFIC_ANNOTATION_FOR_TESTS, base::DoNothing()); + auto* request = static_cast<ResumableUploadRequest*>(connector_request.get()); + request->SetMetadataRequestHeaders(&resource_request); + + VerifyMetadataRequestHeaders(std::move(resource_request), "9"); +} + +TEST_F(ResumableUploadRequestTest, + GeneratesCorrectMetadataHeaders_FileRequest_Encrypted) { + network::ResourceRequest resource_request; + auto connector_request = ResumableUploadRequest::CreateFileRequest( + nullptr, GURL(), "metadata", BinaryUploadService::Result::FILE_ENCRYPTED, + CreateFile("my_file_name.foo", "file_data"), 9, + TRAFFIC_ANNOTATION_FOR_TESTS, base::DoNothing()); auto* request = static_cast<ResumableUploadRequest*>(connector_request.get()); request->SetMetadataRequestHeaders(&resource_request); @@ -154,8 +188,9 @@ GeneratesCorrectMetadataHeaders_PageRequest) { network::ResourceRequest resource_request; auto connector_request = ResumableUploadRequest::CreatePageRequest( - nullptr, GURL(), "metadata", CreatePage("print_data"), - TRAFFIC_ANNOTATION_FOR_TESTS, base::DoNothing()); + nullptr, GURL(), "metadata", BinaryUploadService::Result::SUCCESS, + CreatePage("print_data"), TRAFFIC_ANNOTATION_FOR_TESTS, + base::DoNothing()); auto* request = static_cast<ResumableUploadRequest*>(connector_request.get()); request->SetMetadataRequestHeaders(&resource_request); @@ -167,6 +202,17 @@ public testing::WithParamInterface<bool> { public: bool is_file_request() { return GetParam(); } + + std::unique_ptr<MockResumableUploadRequest> CreateRequest( + ConnectorUploadRequest::Callback callback) { + return is_file_request() + ? CreateFileRequest("file content", + BinaryUploadService::Result::SUCCESS, + std::move(callback)) + : CreatePageRequest("page content", + BinaryUploadService::Result::SUCCESS, + std::move(callback)); + } }; INSTANTIATE_TEST_SUITE_P(, @@ -189,22 +235,11 @@ body = network::GetUploadData(request); })); + auto callback = base::BindLambdaForTesting( + [&run_loop](bool success, int http_status, + const std::string& response_data) { run_loop.Quit(); }); std::unique_ptr<MockResumableUploadRequest> mock_request = - is_file_request() - ? CreateFileRequest( - "file content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - run_loop.Quit(); - })) - : CreatePageRequest( - "page content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - run_loop.Quit(); - })); + CreateRequest(std::move(callback)); mock_request->Start(); ASSERT_EQ(test_url_loader_factory_.NumPending(), 1); @@ -219,28 +254,16 @@ base::RunLoop run_loop; std::string body; + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_FALSE(success); + EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); + EXPECT_EQ("response", response_data); + run_loop.Quit(); + }); std::unique_ptr<MockResumableUploadRequest> mock_request = - is_file_request() - ? CreateFileRequest( - "file content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_FALSE(success); - EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); - EXPECT_EQ("response", response_data); - run_loop.Quit(); - })) - : CreatePageRequest( - "page content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_FALSE(success); - EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); - EXPECT_EQ("response", response_data); - run_loop.Quit(); - })); + CreateRequest(std::move(callback)); mock_request->Start(); ASSERT_EQ(test_url_loader_factory_.NumPending(), 1); @@ -259,28 +282,16 @@ base::RunLoop run_loop; std::string body; + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_TRUE(success); + EXPECT_EQ(net::HTTP_OK, http_status); + EXPECT_EQ("final_response", response_data); + run_loop.Quit(); + }); std::unique_ptr<MockResumableUploadRequest> mock_request = - is_file_request() - ? CreateFileRequest( - "file content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_TRUE(success); - EXPECT_EQ(net::HTTP_OK, http_status); - EXPECT_EQ("response", response_data); - run_loop.Quit(); - })) - : CreatePageRequest( - "page content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_TRUE(success); - EXPECT_EQ(net::HTTP_OK, http_status); - EXPECT_EQ("response", response_data); - run_loop.Quit(); - })); + CreateRequest(std::move(callback)); mock_request->Start(); ASSERT_EQ(test_url_loader_factory_.NumPending(), 1); @@ -289,7 +300,7 @@ auto head = network::CreateURLResponseHead(net::HTTP_OK); head->headers->AddHeader("X-Goog-Upload-Status", "final"); test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList( - pending_request, std::move(head), "response", + pending_request, std::move(head), "final_response", network::URLLoaderCompletionStatus(net::OK)); run_loop.Run(); @@ -301,6 +312,16 @@ public testing::WithParamInterface<bool> { public: bool is_file_request() { return GetParam(); } + + std::unique_ptr<MockResumableUploadRequest> CreateRequest( + BinaryUploadService::Result get_data_result, + ConnectorUploadRequest::Callback callback) { + return is_file_request() + ? CreateFileRequest("file content", get_data_result, + std::move(callback)) + : CreatePageRequest("page content", get_data_result, + std::move(callback)); + } }; INSTANTIATE_TEST_SUITE_P(, @@ -313,28 +334,16 @@ std::string content_upload_command; std::string content_upload_offset; + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_TRUE(success); + EXPECT_EQ(net::HTTP_OK, http_status); + EXPECT_EQ("final_response", response_data); + run_loop.Quit(); + }); std::unique_ptr<MockResumableUploadRequest> mock_request = - is_file_request() - ? CreateFileRequest( - "file content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_TRUE(success); - EXPECT_EQ(net::HTTP_OK, http_status); - EXPECT_EQ("final_response", response_data); - run_loop.Quit(); - })) - : CreatePageRequest( - "page content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_TRUE(success); - EXPECT_EQ(net::HTTP_OK, http_status); - EXPECT_EQ("final_response", response_data); - run_loop.Quit(); - })); + CreateRequest(BinaryUploadService::Result::SUCCESS, std::move(callback)); test_url_loader_factory_.SetInterceptor( base::BindLambdaForTesting([&](const network::ResourceRequest& request) { @@ -368,49 +377,99 @@ mock_request->Start(); run_loop.Run(); - if (is_file_request()) { - EXPECT_EQ("file content", - enterprise_connectors::test::GetBodyFromFileOrPageRequest( - mock_request->data_pipe_getter_for_testing())); - } else { - EXPECT_EQ("page content", - enterprise_connectors::test::GetBodyFromFileOrPageRequest( - mock_request->data_pipe_getter_for_testing())); - } + EXPECT_EQ(is_file_request() ? "file content" : "page content", + enterprise_connectors::test::GetBodyFromFileOrPageRequest( + mock_request->data_pipe_getter_for_testing())); EXPECT_EQ(content_upload_method, "POST"); EXPECT_EQ(content_upload_command, "upload, finalize"); EXPECT_EQ(content_upload_offset, "0"); EXPECT_EQ(mock_request->GetUploadInfo(), "Resumable - Full content scan"); } +TEST_P(ResumableUploadSendContentRequestTest, HandlesFileTooLarge) { + base::RunLoop run_loop; + + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_FALSE(success); + EXPECT_EQ(net::HTTP_BAD_REQUEST, http_status); + run_loop.Quit(); + }); + std::unique_ptr<MockResumableUploadRequest> mock_request = CreateRequest( + BinaryUploadService::Result::FILE_TOO_LARGE, std::move(callback)); + + test_url_loader_factory_.SetInterceptor( + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + // Return a response that asks for more data. + if (request.url == GURL("https://google.com")) { + auto metadata_response_head = + network::CreateURLResponseHead(net::HTTP_OK); + metadata_response_head->headers->AddHeader("X-Goog-Upload-Status", + "active"); + metadata_response_head->headers->AddHeader("X-Goog-Upload-URL", + kUploadUrl); + test_url_loader_factory_.AddResponse( + GURL("https://google.com"), std::move(metadata_response_head), + "metadata_response", network::URLLoaderCompletionStatus(net::OK)); + } else { + NOTREACHED(); + } + })); + mock_request->Start(); + run_loop.Run(); +} + +TEST_P(ResumableUploadSendContentRequestTest, HandlesEncryptedFile) { + base::RunLoop run_loop; + + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_FALSE(success); + EXPECT_EQ(net::HTTP_BAD_REQUEST, http_status); + run_loop.Quit(); + }); + std::unique_ptr<MockResumableUploadRequest> mock_request = CreateRequest( + BinaryUploadService::Result::FILE_ENCRYPTED, std::move(callback)); + + test_url_loader_factory_.SetInterceptor( + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + // Return a response that asks for more data. + if (request.url == GURL("https://google.com")) { + auto metadata_response_head = + network::CreateURLResponseHead(net::HTTP_OK); + metadata_response_head->headers->AddHeader("X-Goog-Upload-Status", + "active"); + metadata_response_head->headers->AddHeader("X-Goog-Upload-URL", + kUploadUrl); + test_url_loader_factory_.AddResponse( + GURL("https://google.com"), std::move(metadata_response_head), + "metadata_response", network::URLLoaderCompletionStatus(net::OK)); + } else { + NOTREACHED(); + } + })); + mock_request->Start(); + run_loop.Run(); +} + TEST_P(ResumableUploadSendContentRequestTest, HandlesFailedContentScan) { base::RunLoop run_loop; std::string content_upload_method; std::string content_upload_command; std::string content_upload_offset; + auto callback = + base::BindLambdaForTesting([&run_loop](bool success, int http_status, + const std::string& response_data) { + EXPECT_FALSE(success); + EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); + EXPECT_EQ("final_response", response_data); + run_loop.Quit(); + }); std::unique_ptr<MockResumableUploadRequest> mock_request = - is_file_request() - ? CreateFileRequest( - "file content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_FALSE(success); - EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); - EXPECT_EQ("final_response", response_data); - run_loop.Quit(); - })) - : CreatePageRequest( - "page content", - base::BindLambdaForTesting( - [&run_loop](bool success, int http_status, - const std::string& response_data) { - EXPECT_FALSE(success); - EXPECT_EQ(net::HTTP_UNAUTHORIZED, http_status); - EXPECT_EQ("final_response", response_data); - run_loop.Quit(); - })); + CreateRequest(BinaryUploadService::Result::SUCCESS, std::move(callback)); test_url_loader_factory_.SetInterceptor( base::BindLambdaForTesting([&](const network::ResourceRequest& request) { @@ -442,15 +501,9 @@ mock_request->Start(); run_loop.Run(); - if (is_file_request()) { - EXPECT_EQ("file content", - enterprise_connectors::test::GetBodyFromFileOrPageRequest( - mock_request->data_pipe_getter_for_testing())); - } else { - EXPECT_EQ("page content", - enterprise_connectors::test::GetBodyFromFileOrPageRequest( - mock_request->data_pipe_getter_for_testing())); - } + EXPECT_EQ(is_file_request() ? "file content" : "page content", + enterprise_connectors::test::GetBodyFromFileOrPageRequest( + mock_request->data_pipe_getter_for_testing())); EXPECT_EQ(content_upload_method, "POST"); EXPECT_EQ(content_upload_command, "upload, finalize"); EXPECT_EQ(content_upload_offset, "0");
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc index cda50d0..760b2ca 100644 --- a/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc +++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc
@@ -839,8 +839,16 @@ EXPECT_EQ(item->GetState(), download::DownloadItem::INTERRUPTED); } +// When the resumable protocol is used for deep scans, the fact that the +// a file is password protected does not affect whether it is blocked or +// not. The final verdict is determined by the server. So this test +// applies only to the multi-part upload protocol. IN_PROC_BROWSER_TEST_P(DownloadDeepScanningBrowserTest, - PasswordProtectedTxtFilesAreBlocked) { + PasswordProtectedTxtFilesAreBlocked_MultipartOnly) { + if (is_resumable()) { + return; + } + // This allows the blocking DM token reads happening on profile-Connector // triggers. base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/chrome/browser/safe_browsing/download_protection/download_feedback_unittest.cc b/chrome/browser/safe_browsing/download_protection/download_feedback_unittest.cc index ba130312..03d0710 100644 --- a/chrome/browser/safe_browsing/download_protection/download_feedback_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection/download_feedback_unittest.cc
@@ -87,6 +87,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& file_path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -95,6 +96,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ConnectorUploadRequest::Callback callback) override; @@ -117,6 +119,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, const base::FilePath& file_path, uint64_t file_size, const net::NetworkTrafficAnnotationTag& traffic_annotation, @@ -133,6 +136,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& base_url, const std::string& metadata, + BinaryUploadService::Result get_data_result, base::ReadOnlySharedMemoryRegion page_region, const net::NetworkTrafficAnnotationTag& traffic_annotation, ConnectorUploadRequest::Callback callback) {
diff --git a/chrome/browser/search/most_visited_iframe_source_unittest.cc b/chrome/browser/search/most_visited_iframe_source_unittest.cc index 94c3ba48..26faf542 100644 --- a/chrome/browser/search/most_visited_iframe_source_unittest.cc +++ b/chrome/browser/search/most_visited_iframe_source_unittest.cc
@@ -77,7 +77,7 @@ std::string response_string() { if (response_.get()) { - return std::string(response_->front_as<char>(), response_->size()); + return std::string(base::as_string_view(*response_)); } return ""; }
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc index 56b1f442..9a4f74e 100644 --- a/chrome/browser/sessions/tab_restore_browsertest.cc +++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -1110,8 +1110,8 @@ EXPECT_EQ(4, browser->tab_strip_model()->count()); } -// Test is flaky on Win. https://crbug.com/1241761. -#if BUILDFLAG(IS_WIN) +// Test is flaky on Win and Mac. crbug.com/1241761, crbug.com/330838232. +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) #define MAYBE_TabsFromRestoredWindowsAreLoadedGradually \ DISABLED_TabsFromRestoredWindowsAreLoadedGradually #else
diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc index 3736d93..6ee6156e 100644 --- a/chrome/browser/sessions/tab_restore_service_unittest.cc +++ b/chrome/browser/sessions/tab_restore_service_unittest.cc
@@ -117,34 +117,14 @@ MOCK_CONST_METHOD0(GetRestoredBounds, const gfx::Rect()); MOCK_CONST_METHOD0(GetRestoredState, ui::WindowShowState()); MOCK_CONST_METHOD0(GetWorkspace, std::string()); - MOCK_METHOD(sessions::LiveTab*, AddRestoredTab, - ((const std::vector<SerializedNavigationEntry>&), - int, - int, - (const std::string&), - std::optional<tab_groups::TabGroupId>, - (const tab_groups::TabGroupVisualData&), - bool, - bool, - const sessions::tab_restore::PlatformSpecificTabData*, - (const sessions::SerializedUserAgentOverride&), - (const std::map<std::string, std::string>&), - (const SessionID*)), + ((const sessions::tab_restore::Tab&), int, bool), (override)); - MOCK_METHOD(sessions::LiveTab*, ReplaceRestoredTab, - ((const std::vector<SerializedNavigationEntry>&), - std::optional<tab_groups::TabGroupId>, - int, - (const std::string&), - (const sessions::tab_restore::PlatformSpecificTabData*), - (const sessions::SerializedUserAgentOverride&), - (const std::map<std::string, std::string>&)), + ((const sessions::tab_restore::Tab&)), (override)); - MOCK_METHOD0(CloseTab, void()); };
diff --git a/chrome/browser/shortcuts/BUILD.gn b/chrome/browser/shortcuts/BUILD.gn index 3e2cc02f..5b3c15c3 100644 --- a/chrome/browser/shortcuts/BUILD.gn +++ b/chrome/browser/shortcuts/BUILD.gn
@@ -13,6 +13,8 @@ "document_icon_fetcher.h", "fetch_icons_from_document_task.cc", "fetch_icons_from_document_task.h", + "platform_util_mac.h", + "platform_util_mac.mm", ] deps = [ @@ -47,3 +49,17 @@ "//url", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ "platform_util_mac_unittest.mm" ] + + deps = [ + ":shortcuts", + "//base", + "//base/test:test_support", + "//testing/gtest", + "//ui/gfx:test_support", + ] +}
diff --git a/chrome/browser/shortcuts/platform_util_mac.h b/chrome/browser/shortcuts/platform_util_mac.h new file mode 100644 index 0000000..21a3b69 --- /dev/null +++ b/chrome/browser/shortcuts/platform_util_mac.h
@@ -0,0 +1,39 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SHORTCUTS_PLATFORM_UTIL_MAC_H_ +#define CHROME_BROWSER_SHORTCUTS_PLATFORM_UTIL_MAC_H_ + +#include "base/functional/callback_forward.h" + +@class NSError; +@class NSImage; +@class NSURL; + +namespace base { +class FilePath; +} + +namespace shortcuts { + +// Wrapper around NSWorkspace setIcon:forFile: that can be called from any +// thread. While the underlying NSWorkspace method can also be called from any +// thread, it is not reentrancy safe (i.e. multiple calls to it need to be +// sequenced). This wrapper takes care of the sequencing needed. The `callback` +// will be called on the calling sequence. +void SetIconForFile(NSImage* image, + const base::FilePath& file, + base::OnceCallback<void(bool)> callback); + +// Wrapper around NSWorkspace setDefaultApplicationAtURL:toOpenFileAtURL:. The +// NSWorkspace method only exists on macOS 12.0 and newer; this method polyfills +// its implementation for older macOS versions. +void SetDefaultApplicationToOpenFile( + NSURL* file_url, + NSURL* application_url, + base::OnceCallback<void(NSError*)> callback); + +} // namespace shortcuts + +#endif // CHROME_BROWSER_SHORTCUTS_PLATFORM_UTIL_MAC_H_
diff --git a/chrome/browser/shortcuts/platform_util_mac.mm b/chrome/browser/shortcuts/platform_util_mac.mm new file mode 100644 index 0000000..11d4416 --- /dev/null +++ b/chrome/browser/shortcuts/platform_util_mac.mm
@@ -0,0 +1,66 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/shortcuts/platform_util_mac.h" + +#import <AppKit/AppKit.h> + +#import "base/apple/foundation_util.h" +#include "base/files/file_path.h" +#include "base/functional/callback.h" +#include "base/functional/callback_helpers.h" +#include "base/task/bind_post_task.h" +#include "base/task/lazy_thread_pool_task_runner.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/task_traits.h" + +namespace shortcuts { + +namespace { +base::LazyThreadPoolSequencedTaskRunner g_set_icon_task_runner = + LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER( + base::TaskTraits({base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})); +} // namespace + +void SetIconForFile(NSImage* image, + const base::FilePath& file, + base::OnceCallback<void(bool)> callback) { + g_set_icon_task_runner.Get()->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](NSImage* image, const base::FilePath& file) { + return [NSWorkspace.sharedWorkspace + setIcon:image + forFile:base::apple::FilePathToNSString(file) + options:NSExcludeQuickDrawElementsIconCreationOption]; + }, + image, file), + std::move(callback)); +} + +void SetDefaultApplicationToOpenFile( + NSURL* file_url, + NSURL* application_url, + base::OnceCallback<void(NSError*)> callback) { + if (@available(macOS 12.0, *)) { + [NSWorkspace.sharedWorkspace + setDefaultApplicationAtURL:application_url + toOpenFileAtURL:file_url + completionHandler:base::CallbackToBlock( + base::BindPostTaskToCurrentDefault( + std::move(callback)))]; + } else { + // Older macOS versions don't have a nice API for this, but doing what + // setDefaultApplicationAtURL:toOpenFileAtURL: does directly seems to work + // just fine on those versions as well, so that is what this branch does. + NSError* error = nil; + [file_url setResourceValue:application_url + forKey:@"_NSURLStrongBindingKey" + error:&error]; + base::BindPostTaskToCurrentDefault(std::move(callback)).Run(error); + } +} + +} // namespace shortcuts
diff --git a/chrome/browser/shortcuts/platform_util_mac_unittest.mm b/chrome/browser/shortcuts/platform_util_mac_unittest.mm new file mode 100644 index 0000000..26b01e8 --- /dev/null +++ b/chrome/browser/shortcuts/platform_util_mac_unittest.mm
@@ -0,0 +1,69 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/shortcuts/platform_util_mac.h" + +#import <AppKit/AppKit.h> + +#import "base/apple/foundation_util.h" +#include "base/files/scoped_temp_file.h" +#include "base/test/task_environment.h" +#include "base/test/test_future.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "ui/gfx/image/image_unittest_util.h" + +namespace shortcuts { + +TEST(ShortcutsPlatformUtilMacTest, SetIconForFile) { + base::test::TaskEnvironment task_environment; + + base::ScopedTempFile test_file1; + ASSERT_TRUE(test_file1.Create()); + base::ScopedTempFile test_file2; + ASSERT_TRUE(test_file2.Create()); + + base::test::TestFuture<bool> result1; + SetIconForFile(gfx::test::CreateImage(/*size=*/32, SK_ColorRED).ToNSImage(), + test_file1.path(), result1.GetCallback()); + base::test::TestFuture<bool> result2; + SetIconForFile(gfx::test::CreateImage(/*size=*/32, SK_ColorBLUE).ToNSImage(), + test_file2.path(), result2.GetCallback()); + + EXPECT_TRUE(result1.Get()); + EXPECT_TRUE(result2.Get()); + + NSImage* image1 = [NSWorkspace.sharedWorkspace + iconForFile:base::apple::FilePathToNSString(test_file1.path())]; + SkColor color1 = gfx::test::GetPlatformImageColor(image1, 0, 0); + gfx::test::CheckColors(SK_ColorRED, color1); + + NSImage* image2 = [NSWorkspace.sharedWorkspace + iconForFile:base::apple::FilePathToNSString(test_file2.path())]; + SkColor color2 = gfx::test::GetPlatformImageColor(image2, 0, 0); + gfx::test::CheckColors(SK_ColorBLUE, color2); +} + +TEST(ShortcutsPlatformUtilMacTest, SetDefaultApplicationToOpenFile) { + base::test::TaskEnvironment task_environment; + + base::ScopedTempFile test_file; + ASSERT_TRUE(test_file.Create()); + NSURL* file_url = base::apple::FilePathToNSURL(test_file.path()); + + // This test needs an arbitrary (but valid) url for an application. Safari + // always exists, so is as good as any app to use. + NSURL* app_url = [NSWorkspace.sharedWorkspace + URLForApplicationWithBundleIdentifier:@"com.apple.Safari"]; + + base::test::TestFuture<NSError*> result; + SetDefaultApplicationToOpenFile(file_url, app_url, result.GetCallback()); + EXPECT_FALSE(result.Get()); + + NSURL* got_app_url = + [NSWorkspace.sharedWorkspace URLForApplicationToOpenURL:file_url]; + EXPECT_NSEQ(app_url, got_app_url); +} + +} // namespace shortcuts
diff --git a/chrome/browser/ssl/sct_reporting_service_browsertest.cc b/chrome/browser/ssl/sct_reporting_service_browsertest.cc index afbe634..178d5ef 100644 --- a/chrome/browser/ssl/sct_reporting_service_browsertest.cc +++ b/chrome/browser/ssl/sct_reporting_service_browsertest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/ssl/sct_reporting_service.h" + #include <memory> #include <tuple> @@ -23,7 +25,6 @@ #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/cert_verifier_browser_test.h" -#include "chrome/browser/ssl/sct_reporting_service.h" #include "chrome/browser/ssl/sct_reporting_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_constants.h" @@ -59,6 +60,7 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/mojom/ct_log_info.mojom.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/proto/sct_audit_report.pb.h" #include "services/network/test/test_url_loader_factory.h" @@ -868,6 +870,18 @@ mock_cert_verifier()->AddResultForCertAndHost( https_server()->GetCertificate().get(), "hashdance.test", verify_result, net::OK); + network::mojom::CTLogInfoPtr log(std::in_place); + std::string googleLogIdAsString( + reinterpret_cast<const char*>(kTestGoogleLogId), + sizeof(kTestGoogleLogId)); + log->id = googleLogIdAsString; + log->mmd = base::Seconds(86400); + std::vector<network::mojom::CTLogInfoPtr> log_list; + log_list.emplace_back(std::move(log)); + base::RunLoop run_loop; + content::GetNetworkService()->UpdateCtLogList(std::move(log_list), + run_loop.QuitClosure()); + run_loop.Run(); } private:
diff --git a/chrome/browser/subresource_filter/ruleset_browsertest.cc b/chrome/browser/subresource_filter/ruleset_browsertest.cc index 514a763..013e183 100644 --- a/chrome/browser/subresource_filter/ruleset_browsertest.cc +++ b/chrome/browser/subresource_filter/ruleset_browsertest.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/testing_browser_process.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/subresource_filter/content/shared/browser/ruleset_service.h" #include "components/subresource_filter/core/browser/async_document_subresource_filter.h" #include "components/subresource_filter/core/browser/async_document_subresource_filter_test_utils.h" @@ -232,7 +233,8 @@ public: SubresourceFilterBrowserTestFingerprintingProtectionDisabled() { feature_list_.InitAndDisableFeature( - features::kEnableFingerprintingProtectionBlocklist); + fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter); } private: @@ -251,7 +253,8 @@ public: SubresourceFilterBrowserTestFingerprintingProtectionEnabled() { feature_list_.InitAndEnableFeature( - features::kEnableFingerprintingProtectionBlocklist); + fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter); } private:
diff --git a/chrome/browser/support_tool/screenshot_data_collector_unittest.cc b/chrome/browser/support_tool/screenshot_data_collector_unittest.cc index c032212..45c1d56c 100644 --- a/chrome/browser/support_tool/screenshot_data_collector_unittest.cc +++ b/chrome/browser/support_tool/screenshot_data_collector_unittest.cc
@@ -109,5 +109,5 @@ ReadFileContents(output_dir.Append(FILE_PATH_LITERAL("screenshot")) .AddExtension(FILE_PATH_LITERAL(".jpg")), output_file_contents); - EXPECT_EQ(output_file_contents, jpeg_data_->data()); + EXPECT_EQ(output_file_contents, jpeg_data_->as_string()); }
diff --git a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc index 5d3c48a..41a16fdf 100644 --- a/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc +++ b/chrome/browser/sync/prefs/chrome_syncable_prefs_database.cc
@@ -333,6 +333,7 @@ kProfileDefaultContentSettingValuesTrackingProtection = 100275, kShowForwardButton = 100276, kAccessibilityMagnifierFollowsSts = 100277, + kAccessibilityReadAnythingLanguagesEnabled = 100278, // See components/sync_preferences/README.md about adding new entries here. // vvvvv IMPORTANT! vvvvv // Note to the reviewer: IT IS YOUR RESPONSIBILITY to ensure that new syncable @@ -432,6 +433,10 @@ {syncable_prefs_ids::kAccessibilityReadAnythingLinksEnabled, syncer::PREFERENCES, sync_preferences::PrefSensitivity::kNone, sync_preferences::MergeBehavior::kNone}}, + {prefs::kAccessibilityReadAnythingLanguagesEnabled, + {syncable_prefs_ids::kAccessibilityReadAnythingLanguagesEnabled, + syncer::PREFERENCES, sync_preferences::PrefSensitivity::kNone, + sync_preferences::MergeBehavior::kNone}}, {prefs::kLensRegionSearchEnabled, {syncable_prefs_ids::kLensRegionSearchEnabled, syncer::PREFERENCES, sync_preferences::PrefSensitivity::kNone,
diff --git a/chrome/browser/tab/web_contents_state.cc b/chrome/browser/tab/web_contents_state.cc index 791b385..29e92e66 100644 --- a/chrome/browser/tab/web_contents_state.cc +++ b/chrome/browser/tab/web_contents_state.cc
@@ -116,8 +116,9 @@ !iterator->ReadString(&str_referrer) || !iterator->ReadString16(&title) || !iterator->ReadString(&content_state) || - !iterator->ReadInt(&transition_type_int)) + !iterator->ReadInt(&transition_type_int)) { return; + } // Write back the fields that were just read. v2_pickle.WriteInt(i); @@ -201,8 +202,9 @@ !iterator->ReadString(&virtual_url_spec) || !iterator->ReadString16(&title) || !iterator->ReadString(&content_state) || - !iterator->ReadInt(&transition_type_int)) + !iterator->ReadInt(&transition_type_int)) { return; + } // Write back the fields that were just read. v2_pickle.WriteInt(index); @@ -212,29 +214,35 @@ v2_pickle.WriteInt(transition_type_int); int type_mask = 0; - if (!iterator->ReadInt(&type_mask)) + if (!iterator->ReadInt(&type_mask)) { continue; + } v2_pickle.WriteInt(type_mask); std::string referrer_spec; - if (iterator->ReadString(&referrer_spec)) + if (iterator->ReadString(&referrer_spec)) { v2_pickle.WriteString(referrer_spec); + } int policy_int; - if (iterator->ReadInt(&policy_int)) + if (iterator->ReadInt(&policy_int)) { v2_pickle.WriteInt(policy_int); + } std::string original_request_url_spec; - if (iterator->ReadString(&original_request_url_spec)) + if (iterator->ReadString(&original_request_url_spec)) { v2_pickle.WriteString(original_request_url_spec); + } bool is_overriding_user_agent; - if (iterator->ReadBool(&is_overriding_user_agent)) + if (iterator->ReadBool(&is_overriding_user_agent)) { v2_pickle.WriteBool(is_overriding_user_agent); + } int64_t timestamp_internal_value = 0; - if (iterator->ReadInt64(×tamp_internal_value)) + if (iterator->ReadInt64(×tamp_internal_value)) { v2_pickle.WriteInt64(timestamp_internal_value); + } // Force output of search_terms v2_pickle.WriteString16(std::u16string()); @@ -299,8 +307,9 @@ base::PickleIterator tab_navigation_pickle_iterator( tab_navigation_pickle); sessions::SerializedNavigationEntry nav; - if (!nav.ReadFromPickle(&tab_navigation_pickle_iterator)) + if (!nav.ReadFromPickle(&tab_navigation_pickle_iterator)) { return false; // If we failed to read a navigation, give up on others. + } navigations->push_back(nav); } @@ -308,8 +317,9 @@ // Validate the data. if (*current_entry_index < 0 || - *current_entry_index >= static_cast<int>(navigations->size())) + *current_entry_index >= static_cast<int>(navigations->size())) { return false; + } return true; } @@ -370,16 +380,18 @@ ScopedJavaLocalRef<jobject> WebContentsState::GetContentsStateAsByteBuffer( JNIEnv* env, content::WebContents* web_contents) { - if (!web_contents) + if (!web_contents) { return ScopedJavaLocalRef<jobject>(); + } content::NavigationController& controller = web_contents->GetController(); const int entry_count = controller.GetEntryCount(); // Don't try to persist initial NavigationEntry, as it is not actually // associated with any navigation and will just result in about:blank on // session restore. - if (controller.GetLastCommittedEntry()->IsInitialEntry()) + if (controller.GetLastCommittedEntry()->IsInitialEntry()) { return ScopedJavaLocalRef<jobject>(); + } std::vector<content::NavigationEntry*> navigations(entry_count); for (int i = 0; i < entry_count; ++i) { @@ -403,8 +415,9 @@ bool success = ExtractNavigationEntries(buffer, saved_state_version, &is_off_the_record, ¤t_entry_index, &navigations); - if (!success) + if (!success) { return ScopedJavaLocalRef<jobject>(); + } std::vector<sessions::SerializedNavigationEntry> new_navigations; int deleted_navigations = 0; @@ -414,14 +427,16 @@ deleted_navigations++; } else { // Adjust indices according to number of deleted navigations. - if (current_entry_index == navigation.index()) + if (current_entry_index == navigation.index()) { current_entry_index -= deleted_navigations; + } navigation.set_index(navigation.index() - deleted_navigations); new_navigations.push_back(std::move(navigation)); } } - if (deleted_navigations == 0) + if (deleted_navigations == 0) { return ScopedJavaLocalRef<jobject>(); + } return WriteSerializedNavigationsAsByteBuffer( env, is_off_the_record, new_navigations, current_entry_index); @@ -437,8 +452,9 @@ bool success = ExtractNavigationEntries(buffer, saved_state_version, &is_off_the_record, ¤t_entry_index, &navigations); - if (!success) + if (!success) { return ScopedJavaLocalRef<jstring>(); + } sessions::SerializedNavigationEntry nav_entry = navigations.at(current_entry_index); @@ -455,8 +471,9 @@ bool success = ExtractNavigationEntries(buffer, saved_state_version, &is_off_the_record, ¤t_entry_index, &navigations); - if (!success) + if (!success) { return ScopedJavaLocalRef<jstring>(); + } sessions::SerializedNavigationEntry nav_entry = navigations.at(current_entry_index); @@ -477,10 +494,11 @@ span, saved_state_version, initially_hidden, no_renderer) .release(); - if (web_contents) + if (web_contents) { return web_contents->GetJavaWebContents(); - else + } else { return ScopedJavaLocalRef<jobject>(); + } } std::unique_ptr<WebContents> WebContentsState::RestoreContentsFromByteBuffer( @@ -504,8 +522,9 @@ bool success = ExtractNavigationEntries(buffer, saved_state_version, &is_off_the_record, ¤t_entry_index, &navigations); - if (!success) + if (!success) { return nullptr; + } Profile* profile = ProfileManager::GetActiveUserProfile(); std::vector<std::unique_ptr<content::NavigationEntry>> entries = @@ -548,8 +567,9 @@ } url::Origin initiator_origin; - if (jinitiator_origin) + if (jinitiator_origin) { initiator_origin = url::Origin::FromJavaObject(jinitiator_origin); + } // TODO(crbug.com/40062134): Deal with getting initiator_base_url // plumbed here too. std::unique_ptr<content::NavigationEntry> entry(
diff --git a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java index a17ec44..6546b3f 100644 --- a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java +++ b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java
@@ -155,7 +155,7 @@ mActualGroupCount++; boolean didCreateNewGroup = true; - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { // If the destination group already has an assigned color, then this action is not // for a new tab group creation. Currently, the only case where this would be called // and it is not a new tab group creation is when a tab group is restored from the @@ -242,7 +242,7 @@ boolean didCreateNewGroup = !isTabInTabGroup(sourceTab) && !isTabInTabGroup(destinationTab); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { destinationGroupColorId = TabGroupColorUtils.getTabGroupColor(destinationRootId); // If the destination group already has an assigned color, then this action is not // for a new tab group creation. Currently, the only case where this would be called @@ -370,7 +370,7 @@ int destinationIndexInTabModel = getTabModelDestinationIndex(destinationTab); String destinationGroupTitle = TabGroupTitleUtils.getTabGroupTitle(destinationRootId); int destinationGroupColorId = INVALID_COLOR_ID; - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_PARITY_ANDROID)) { + if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { destinationGroupColorId = TabGroupColorUtils.getTabGroupColor(destinationRootId); }
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 4420a8f..3535a0b 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -437,9 +437,8 @@ PngMap::const_iterator exact_png_it = png_map_.find(scale_factor); if (exact_png_it != png_map_.end()) { SkBitmap bitmap; - if (!gfx::PNGCodec::Decode(exact_png_it->second->front(), - exact_png_it->second->size(), - &bitmap)) { + if (!gfx::PNGCodec::Decode(exact_png_it->second->data(), + exact_png_it->second->size(), &bitmap)) { NOTREACHED(); return gfx::ImageSkiaRep(); } @@ -469,7 +468,7 @@ bitmap_map_.find(available_scale_factor); if (available_bitmap_it == bitmap_map_.end()) { SkBitmap available_bitmap; - if (!gfx::PNGCodec::Decode(available_png_it->second->front(), + if (!gfx::PNGCodec::Decode(available_png_it->second->data(), available_png_it->second->size(), &available_bitmap)) { NOTREACHED(); @@ -1546,7 +1545,7 @@ image_memory_[raw_id] = raw_data; } else { SkBitmap bitmap; - if (gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(), + if (gfx::PNGCodec::Decode(raw_data->data(), raw_data->size(), &bitmap)) { image_skia.AddRepresentation(gfx::ImageSkiaRep( bitmap, ui::GetScaleForResourceScaleFactor(scale_factor))); @@ -1984,8 +1983,7 @@ void BrowserThemePack::AddRawImagesTo(const RawImages& images, RawDataForWriting* out) const { for (const auto& pair : images) { - (*out)[pair.first] = - std::string_view(pair.second->front_as<char>(), pair.second->size()); + (*out)[pair.first] = base::as_string_view(*pair.second); } } @@ -2076,8 +2074,7 @@ int available_raw_id = GetRawIDByPersistentID(prs_id, available_scale_factor); RawImages::const_iterator it = image_memory_.find(available_raw_id); SkBitmap available_bitmap; - if (!gfx::PNGCodec::Decode(it->second->front(), - it->second->size(), + if (!gfx::PNGCodec::Decode(it->second->data(), it->second->size(), &available_bitmap)) { NOTREACHED() << "Unable to decode theme image for prs_id=" << prs_id << " for scale_factor=" << available_scale_factor;
diff --git a/chrome/browser/ui/DEPS b/chrome/browser/ui/DEPS index 51a2d29..cc03f1a 100644 --- a/chrome/browser/ui/DEPS +++ b/chrome/browser/ui/DEPS
@@ -9,6 +9,7 @@ "+components/data_sharing/public", "+components/endpoint_fetcher", "+components/enterprise", + "+components/fingerprinting_protection_filter/browser", "+components/infobars/android", "+components/live_caption", "+components/omnibox",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java index 5110d10..a574041 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
@@ -97,25 +97,4 @@ .setDismissOnTouch(true) .build()); } - - /** - * Show the IPH reminder for the cookie controls icon in the omnibox. - * - * @param iphTimeout The timeout after which the IPH bubble should disappear if it was shown. - * @param stringId Resource id of the string displayed. The string will also be used for - * accessibility. - */ - public void showCookieControlsReminderIPH(int iphTimeout, @StringRes int stringId) { - mUserEducationHelper.requestShowIPH( - new IPHCommandBuilder( - mStatusView.getContext().getResources(), - FeatureConstants.COOKIE_CONTROLS_3PCD_FEATURE, - stringId, - stringId) - .setAutoDismissTimeout(iphTimeout) - .setInsetRect(new Rect()) - .setAnchorView(mStatusView) - .setDismissOnTouch(true) - .build()); - } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHControllerUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHControllerUnitTest.java index 13297a8..3342ab7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHControllerUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHControllerUnitTest.java
@@ -107,20 +107,4 @@ assertNull(cmd.anchorRect); assertEquals(mView, cmd.anchorView); } - - @Test - public void showCookieControlsReminderIPH() { - mController.showCookieControlsReminderIPH(TIMEOUT, IPH_RES_ID); - verify(mHelper).requestShowIPH(mIPHCmdCaptor.capture()); - var cmd = mIPHCmdCaptor.getValue(); - cmd.fetchFromResources(); - - assertEquals(TIMEOUT, cmd.autoDismissTimeout); - assertEquals(IPH_RES_ID, cmd.stringId); - assertEquals(FeatureConstants.COOKIE_CONTROLS_3PCD_FEATURE, cmd.featureName); - assertEquals(STATUS_INSETS, cmd.insetRect); - assertTrue(cmd.dismissOnTouch); - assertNull(cmd.anchorRect); - assertEquals(mView, cmd.anchorView); - } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java index 0e8ca10..3e69335 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -21,7 +21,6 @@ import org.chromium.base.supplier.OneshotSupplier; import org.chromium.base.supplier.Supplier; -import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.merchant_viewer.MerchantTrustSignalsCoordinator; import org.chromium.chrome.browser.omnibox.LocationBarDataProvider; import org.chromium.chrome.browser.omnibox.OmniboxFeatures; @@ -45,8 +44,6 @@ import org.chromium.components.content_settings.CookieBlocking3pcdStatus; import org.chromium.components.content_settings.CookieControlsBridge; import org.chromium.components.content_settings.CookieControlsObserver; -import org.chromium.components.feature_engagement.FeatureConstants; -import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.page_info.PageInfoController; import org.chromium.components.permissions.PermissionDialogController; import org.chromium.components.search_engines.TemplateUrlService; @@ -854,14 +851,7 @@ return; } - Tracker tracker = TrackerFactory.getTrackerForProfile(profile); - if (!tracker.wouldTriggerHelpUI(FeatureConstants.COOKIE_CONTROLS_3PCD_FEATURE)) return; - - animateCookieControlsIcon( - () -> - mPageInfoIPHController.showCookieControlsReminderIPH( - getIPHTimeout(), - R.string.cookie_controls_reminder_iph_message)); + animateCookieControlsIcon(() -> {}); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java index 58ec1fc..c0f8eb5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
@@ -682,118 +682,6 @@ @Test @SmallTest - public void iphReminder3pcd_trackingProtectionsEnabled_cookieBlockingEnabled() { - setupCookieControlsTest(); - - mMediator.onStatusChanged( - /* controls_visible= */ true, - /* protections_on= */ true, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.LIMITED, - /* expiration= */ 0); - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - mMediator.onPageLoadStopped(); - // Cookie controls icon should be shown. - Assert.assertEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - mModel.get(StatusProperties.STATUS_ICON_RESOURCE).getAnimationFinishedCallback().run(); - - // IPH should be shown. - verify(mPageInfoIPHController, times(1)).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - @SmallTest - public void iphReminder3pcd_withNoSecureConnection() { - setupCookieControlsTest(); - - mMediator.updateVerboseStatus(ConnectionSecurityLevel.NONE, false, false); - - mMediator.onStatusChanged( - /* controls_visible= */ true, - /* protections_on= */ true, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.LIMITED, - /* expiration= */ 0); - - mMediator.onPageLoadStopped(); - - // Cookie controls icon should NOT be shown. - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - // IPH should NOT be shown. - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - @SmallTest - public void iphReminder3pcd_onboardingNoticeNotYetAcked() { - setupCookieControlsTest(); - - // No interaction with the Tracking Protection onboarding Notice yet. - doReturn(0).when(mPrefs).getInteger(Pref.TRACKING_PROTECTION_ONBOARDING_ACK_ACTION); - - mMediator.onStatusChanged( - /* controls_visible= */ true, - /* protections_on= */ true, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.LIMITED, - /* expiration= */ 0); - - mMediator.onPageLoadStopped(); - - // Cookie controls icon should NOT be shown. - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - // IPH should NOT be shown. - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - @SmallTest - public void iphReminder3pcd_trackingProtectionsEnabled_cookieBlockingDisabled() { - setupCookieControlsTest(); - - mMediator.onStatusChanged( - /* controls_visible= */ false, - /* protections_on= */ false, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.LIMITED, - /* expiration= */ 0); - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - mMediator.onPageLoadStopped(); - - // Cookie controls icon should NOT be shown. - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - // IPH should NOT be shown. - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - @SmallTest - public void iphReminder3pcd_trackingProtectionsDisabled_cookieBlockingEnabled() { - setupCookieControlsTest(); - - mMediator.onStatusChanged( - /* controls_visible= */ true, - /* protections_on= */ true, - /* enforcement= */ 0, - CookieBlocking3pcdStatus.NOT_IN3PCD, - /* expiration= */ 0); - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - - mMediator.onPageLoadStopped(); - - // Cookie controls icon should NOT be shown. - Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); - // IPH should NOT be shown. - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); - } - - @Test - @SmallTest public void cookieControlsIcon_doesNotAnimateIfWebContentsNull() { setupCookieControlsTest(); @@ -812,7 +700,7 @@ // Cookie controls icon should NOT be shown. Assert.assertNotEquals(COOKIE_CONTROLS_ICON, getIconIdentifierForTesting()); // IPH should NOT be shown. - verify(mPageInfoIPHController, never()).showCookieControlsReminderIPH(anyInt(), anyInt()); + verify(mPageInfoIPHController, never()).showCookieControlsIPH(anyInt(), anyInt()); } @Test
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java index 652810b..931b7d8 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -19,7 +19,6 @@ import org.chromium.base.Callback; import org.chromium.base.ObserverList; import org.chromium.base.supplier.ObservableSupplier; -import org.chromium.base.supplier.OneshotSupplierImpl; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.omnibox.LocationBarDataProvider; @@ -72,16 +71,11 @@ private final @NonNull Callback<Profile> mProfileChangeCallback; private final @NonNull AutocompleteMediator mMediator; private final @NonNull Supplier<ModalDialogManager> mModalDialogManagerSupplier; + private final @NonNull OmniboxSuggestionsDropdownAdapter mAdapter; + private final @NonNull PreWarmingRecycledViewPool mRecycledViewPool; private @Nullable OmniboxSuggestionsDropdown mDropdown; private @NonNull ObserverList<OmniboxSuggestionsDropdownScrollListener> mScrollListenerList = new ObserverList<>(); - private OmniboxSuggestionsDropdownAdapter mAdapter; - private Context mContext; - private boolean mUrlHasFocus; - private OneshotSupplierImpl<OmniboxSuggestionsDropdownAdapter> mAdapterSupplier = - new OneshotSupplierImpl<>(); - private PreWarmingRecycledViewPool mRecycledViewPool; - private final boolean mForcePhoneStyleOmnibox; public AutocompleteCoordinator( @NonNull ViewGroup parent, @@ -104,8 +98,6 @@ mParent = parent; mModalDialogManagerSupplier = modalDialogManagerSupplier; Context context = parent.getContext(); - mContext = context; - mForcePhoneStyleOmnibox = forcePhoneStyleOmnibox; PropertyModel listModel = new PropertyModel(SuggestionListProperties.ALL_KEYS); ModelList listItems = new ModelList(); @@ -149,7 +141,7 @@ this::dropdownOverscrolledToTop); ViewProvider<SuggestionListViewHolder> viewProvider = - createViewProvider(context, listItems); + createViewProvider(context, listItems, forcePhoneStyleOmnibox); viewProvider.whenLoaded( (holder) -> { mDropdown = holder.dropdown; @@ -183,7 +175,7 @@ } private ViewProvider<SuggestionListViewHolder> createViewProvider( - Context context, MVCListAdapter.ModelList modelList) { + Context context, MVCListAdapter.ModelList modelList, boolean forcePhoneStyleOmnibox) { return new ViewProvider<SuggestionListViewHolder>() { private List<Callback<SuggestionListViewHolder>> mCallbacks = new ArrayList<>(); private SuggestionListViewHolder mHolder; @@ -192,9 +184,8 @@ public void inflate() { OmniboxSuggestionsDropdown dropdown = new OmniboxSuggestionsDropdown( - context, mRecycledViewPool, mForcePhoneStyleOmnibox); + context, mRecycledViewPool, forcePhoneStyleOmnibox); - dropdown.getViewGroup().setClipToPadding(false); dropdown.setAdapter(mAdapter); ViewGroup container = @@ -295,7 +286,6 @@ @Override public void onUrlFocusChange(boolean hasFocus) { - mUrlHasFocus = hasFocus; mMediator.onOmniboxSessionStateChange(hasFocus); } @@ -466,7 +456,6 @@ } public @NonNull ModalDialogManager getModalDialogManagerForTest() { - assert mModalDialogManagerSupplier.hasValue(); return mModalDialogManagerSupplier.get(); }
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java index 147651c..e55530d7 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java
@@ -49,6 +49,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeApplicationTestUtils; import org.chromium.components.embedder_support.util.UrlConstants; +import org.chromium.url.GURL; import java.util.Locale; @@ -186,7 +187,8 @@ AppWidgetManager widgetManager = AppWidgetManager.getInstance(mContext); SearchActivityPreferences prefs = - new SearchActivityPreferences("EngineName", "http://engine", true, true, true); + new SearchActivityPreferences( + "EngineName", new GURL("http://engine"), true, true, true); Resources res = mContext.getResources(); float density = res.getDisplayMetrics().density;
diff --git a/chrome/browser/ui/android/searchactivityutils/BUILD.gn b/chrome/browser/ui/android/searchactivityutils/BUILD.gn index 3e90a6f7..e1dbaac 100644 --- a/chrome/browser/ui/android/searchactivityutils/BUILD.gn +++ b/chrome/browser/ui/android/searchactivityutils/BUILD.gn
@@ -25,23 +25,27 @@ ] } -android_library("unit_device_javatests") { - testonly = true - +robolectric_library("junit") { sources = [ "java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java" ] deps = [ ":java", "//base:base_java", "//base:base_java_test_support", + "//base:base_junit_test_support", + "//chrome/browser/incognito:java", + "//chrome/browser/lens:java", "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", "//chrome/browser/search_engines/android:java", + "//chrome/browser/ui/android/omnibox:util_java", "//components/search_engines/android:java", "//content/public/test/android:content_java_test_support", "//third_party/androidx:androidx_test_rules_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/junit", "//third_party/mockito:mockito_java", + "//ui/android:ui_java", + "//url:url_java", ] }
diff --git a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManager.java b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManager.java index 24c8ab8..198ca23 100644 --- a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManager.java +++ b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManager.java
@@ -19,7 +19,6 @@ import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; -import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.shared_preferences.SharedPreferencesManager; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; @@ -49,8 +48,8 @@ /** Name of the Default Search Engine. */ public final @Nullable String searchEngineName; - /** URL of the Default Search Engine. TODO(crbug.com/40241069): migrate this to GURL. */ - public final @Nullable String searchEngineUrl; + /** URL of the Default Search Engine. */ + public final @NonNull GURL searchEngineUrl; /** Whether Voice Search functionality is available. */ public final boolean voiceSearchAvailable; @@ -64,12 +63,12 @@ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public SearchActivityPreferences( @Nullable String searchEngineName, - @Nullable String searchEngineUrl, + @Nullable GURL searchEngineUrl, boolean voiceSearchAvailable, boolean googleLensAvailable, boolean incognitoAvailable) { this.searchEngineName = searchEngineName; - this.searchEngineUrl = searchEngineUrl; + this.searchEngineUrl = searchEngineUrl != null ? searchEngineUrl : GURL.emptyGURL(); this.voiceSearchAvailable = voiceSearchAvailable; this.googleLensAvailable = googleLensAvailable; this.incognitoAvailable = incognitoAvailable; @@ -85,7 +84,7 @@ && googleLensAvailable == other.googleLensAvailable && incognitoAvailable == other.incognitoAvailable && TextUtils.equals(searchEngineName, other.searchEngineName) - && TextUtils.equals(searchEngineUrl, other.searchEngineUrl); + && searchEngineUrl.equals(other.searchEngineUrl); } @Override @@ -147,10 +146,24 @@ */ private static void initializeFromCache() { SharedPreferencesManager manager = ChromeSharedPreferences.getInstance(); + String encodedUrl = manager.readString(SEARCH_WIDGET_SEARCH_ENGINE_URL, null); + + boolean shouldUpdateStorageToSaveSerializedGurl = false; + GURL url = GURL.emptyGURL(); + if (!TextUtils.isEmpty(encodedUrl)) { + url = GURL.deserialize(encodedUrl); + // Deserializing may fail if the URL is not a serialized GURL. + if (url.isEmpty()) { + // This will be slow once, as it will attempt to initialize part of native library. + url = new GURL(encodedUrl); + shouldUpdateStorageToSaveSerializedGurl = true; + } + } + setCurrentlyLoadedPreferences( new SearchActivityPreferences( manager.readString(SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME, null), - manager.readString(SEARCH_WIDGET_SEARCH_ENGINE_URL, null), + url, manager.readBoolean( SEARCH_WIDGET_IS_VOICE_SEARCH_AVAILABLE, DEFAULT_VOICE_SEARCH_AVAILABILITY), @@ -160,7 +173,7 @@ manager.readBoolean( SEARCH_WIDGET_IS_INCOGNITO_AVAILABLE, DEFAULT_INCOGNITO_AVAILABILITY)), - false); + shouldUpdateStorageToSaveSerializedGurl); } /** @@ -201,7 +214,8 @@ SharedPreferencesManager manager = ChromeSharedPreferences.getInstance(); manager.writeString( SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME, prefs.searchEngineName); - manager.writeString(SEARCH_WIDGET_SEARCH_ENGINE_URL, prefs.searchEngineUrl); + manager.writeString( + SEARCH_WIDGET_SEARCH_ENGINE_URL, prefs.searchEngineUrl.serialize()); manager.writeBoolean( SEARCH_WIDGET_IS_VOICE_SEARCH_AVAILABLE, prefs.voiceSearchAvailable); @@ -225,7 +239,6 @@ */ public static void addObserver(@NonNull Consumer<SearchActivityPreferences> observer) { ThreadUtils.assertOnUiThread(); - assert observer != null : "SearchActivityPreferences observer must be valid."; SearchActivityPreferencesManager self = get(); if (!self.mObservers.hasObserver(observer)) { self.mObservers.addObserver(observer); @@ -238,7 +251,6 @@ * browser process must have been fully loaded before calling this. */ public static void onNativeLibraryReady() { - assert LibraryLoader.getInstance().isInitialized(); SearchActivityPreferencesManager self = get(); TemplateUrlService service = TemplateUrlServiceFactory.getForProfile(ProfileManager.getLastUsedRegularProfile()); @@ -282,12 +294,10 @@ * the Native libraries are initialized. */ private void updateDefaultSearchEngineInfo() { - assert LibraryLoader.getInstance().isInitialized(); // Getting an instance of the TemplateUrlService requires that the native library be // loaded, but the TemplateUrlService also itself needs to be initialized. TemplateUrlService service = TemplateUrlServiceFactory.getForProfile(ProfileManager.getLastUsedRegularProfile()); - assert service.isLoaded() : "TemplateUrlServiceFactory is not ready yet."; // Update the URL that we show for zero-suggest. TemplateUrl dseTemplateUrl = service.getDefaultSearchEngineTemplateUrl(); @@ -298,7 +308,7 @@ setCurrentlyLoadedPreferences( new SearchActivityPreferences( dseTemplateUrl.getShortName(), - url.getOrigin().getSpec(), + url.getOrigin(), mCurrentlyLoadedPreferences.voiceSearchAvailable, mCurrentlyLoadedPreferences.googleLensAvailable, mCurrentlyLoadedPreferences.incognitoAvailable),
diff --git a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java index b78f1ae1..5e65e72 100644 --- a/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java +++ b/chrome/browser/ui/android/searchactivityutils/java/src/org/chromium/chrome/browser/ui/searchactivityutils/SearchActivityPreferencesManagerTest.java
@@ -6,8 +6,11 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -19,21 +22,26 @@ import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.SEARCH_WIDGET_SEARCH_ENGINE_URL; -import androidx.test.annotation.UiThreadTest; -import androidx.test.filters.SmallTest; - +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowLooper; +import org.chromium.base.ContextUtils; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.shared_preferences.SharedPreferencesManager; -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.incognito.IncognitoUtils; +import org.chromium.chrome.browser.lens.LensController; +import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionUtil; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; @@ -43,34 +51,62 @@ import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.components.search_engines.TemplateUrlService.LoadListener; import org.chromium.components.search_engines.TemplateUrlService.TemplateUrlServiceObserver; -import org.chromium.content_public.browser.test.NativeLibraryTestUtils; -import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.permissions.AndroidPermissionDelegate; +import org.chromium.url.GURL; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; /** Tests for {@link SearchActivityPreferencesManager}. */ -@RunWith(BaseJUnit4ClassRunner.class) -@Batch(Batch.PER_CLASS) +@RunWith(BaseRobolectricTestRunner.class) +@Config( + shadows = { + SearchActivityPreferencesManagerTest.ShadowIncognitoUtils.class, + SearchActivityPreferencesManagerTest.ShadowLensController.class, + SearchActivityPreferencesManagerTest.ShadowVoiceRecognitionUtil.class, + }) public class SearchActivityPreferencesManagerTest { @Mock private TemplateUrlService mTemplateUrlServiceMock; - @Mock private LibraryLoader mLibraryLoaderMock; - @Mock private TemplateUrl mTemplateUrlMock; - @Mock private Profile mProfile; private LoadListener mTemplateUrlServiceLoadListener; private TemplateUrlServiceObserver mTemplateUrlServiceObserver; + @Implements(IncognitoUtils.class) + public static class ShadowIncognitoUtils { + public static boolean sIsAvailable = true; + + @Implementation + public static boolean isIncognitoModeEnabled() { + return sIsAvailable; + } + } + + @Implements(LensController.class) + public static class ShadowLensController { + public static boolean sIsAvailable = true; + + public static LensController getInstance() { + var controller = mock(LensController.class); + doAnswer(i -> sIsAvailable).when(controller).isLensEnabled(any()); + return controller; + } + } + + @Implements(VoiceRecognitionUtil.class) + public static class ShadowVoiceRecognitionUtil { + public static boolean sIsAvailable = true; + + public static boolean isVoiceSearchEnabled(AndroidPermissionDelegate delegate) { + return sIsAvailable; + } + } + @Before public void setUp() { MockitoAnnotations.initMocks(this); - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); TemplateUrlServiceFactory.setInstanceForTesting(mTemplateUrlServiceMock); - LibraryLoader.setLibraryLoaderForTesting(mLibraryLoaderMock); ProfileManager.setLastUsedProfileForTesting(mProfile); doAnswer( @@ -91,31 +127,42 @@ .when(mTemplateUrlServiceMock) .addObserver(any()); - TestThreadUtils.runOnUiThreadBlocking( - () -> { - SearchActivityPreferencesManager.resetForTesting(); - // Reseta any cached values so we consistently start with a predictable state. - SearchActivityPreferencesManager.resetCachedValues(); - }); + SearchActivityPreferencesManager.resetForTesting(); + // Reset any cached values so we consistently start with a predictable state. + SearchActivityPreferencesManager.resetCachedValues(); // Make sure there were no premature attempts to register observers. Assert.assertNull(mTemplateUrlServiceLoadListener); Assert.assertNull(mTemplateUrlServiceObserver); + + // Purge any pending propagate actions to ensure no side effets later in the tests. + // Needed because `resetCachedValues()` will likely post a task to notify listeners. + ShadowLooper.runUiThreadTasks(); + } + + @After + public void tearDown() { + ShadowLooper.runUiThreadTasks(); + TemplateUrlServiceFactory.setInstanceForTesting(null); + ProfileManager.setLastUsedProfileForTesting(null); + SearchActivityPreferencesManager.resetForTesting(); } @Test - @SmallTest - @UiThreadTest public void preferenceTest_equalWithSameContent() { SearchActivityPreferences p1 = - new SearchActivityPreferences("test", "test.url", true, true, true); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, true, true); SearchActivityPreferences p2 = - new SearchActivityPreferences("test", "test.url", true, true, true); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, true, true); + Assert.assertEquals(p1, p1); + Assert.assertEquals(p2, p2); Assert.assertEquals(p1, p2); Assert.assertEquals(p1.hashCode(), p2.hashCode()); - p1 = new SearchActivityPreferences(null, "test.url", true, false, true); - p2 = new SearchActivityPreferences(null, "test.url", true, false, true); + p1 = new SearchActivityPreferences(null, new GURL("https://test.url"), true, false, true); + p2 = new SearchActivityPreferences(null, new GURL("https://test.url"), true, false, true); Assert.assertEquals(p1, p2); Assert.assertEquals(p1.hashCode(), p2.hashCode()); @@ -131,134 +178,159 @@ } @Test - @SmallTest - @UiThreadTest public void preferenceTest_notEqualWithDifferentVoiceAvailability() { SearchActivityPreferences p1 = - new SearchActivityPreferences("test", "test.url", true, false, false); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, false, false); SearchActivityPreferences p2 = - new SearchActivityPreferences("test", "test.url", false, false, false); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), false, false, false); Assert.assertNotEquals(p1, p2); Assert.assertNotEquals(p1.hashCode(), p2.hashCode()); } @Test - @SmallTest - @UiThreadTest public void preferenceTest_notEqualWithDifferentLensAvailability() { SearchActivityPreferences p1 = - new SearchActivityPreferences("test", "test.url", true, true, false); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, true, false); SearchActivityPreferences p2 = - new SearchActivityPreferences("test", "test.url", true, false, false); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, false, false); Assert.assertNotEquals(p1, p2); Assert.assertNotEquals(p1.hashCode(), p2.hashCode()); } @Test - @SmallTest - @UiThreadTest public void preferenceTest_notEqualWithDifferentIncognitoAvailability() { SearchActivityPreferences p1 = - new SearchActivityPreferences("test", "test.url", true, true, true); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, true, true); SearchActivityPreferences p2 = - new SearchActivityPreferences("test", "test.url", true, true, false); + new SearchActivityPreferences( + "test", new GURL("https://test.url"), true, true, false); Assert.assertNotEquals(p1, p2); Assert.assertNotEquals(p1.hashCode(), p2.hashCode()); } @Test - @SmallTest - @UiThreadTest public void preferenceTest_notEqualWithDifferentSearchEngineName() { SearchActivityPreferences p1 = - new SearchActivityPreferences("Search Engine 1", "test.url", true, true, true); + new SearchActivityPreferences( + "Search Engine 1", new GURL("https://test.url"), true, true, true); SearchActivityPreferences p2 = - new SearchActivityPreferences("Search Engine 2", "test.url", true, true, true); + new SearchActivityPreferences( + "Search Engine 2", new GURL("https://test.url"), true, true, true); Assert.assertNotEquals(p1, p2); Assert.assertNotEquals(p1.hashCode(), p2.hashCode()); } @Test - @SmallTest - @UiThreadTest public void preferenceTest_notEqualWithDifferentSearchEngineUrl() { SearchActivityPreferences p1 = - new SearchActivityPreferences("Google", "www.google.com", true, true, true); + new SearchActivityPreferences( + "Google", new GURL("https://www.google.com"), true, true, true); SearchActivityPreferences p2 = - new SearchActivityPreferences("Google", "www.google.pl", true, true, true); + new SearchActivityPreferences( + "Google", new GURL("https://www.google.pl"), true, true, true); Assert.assertNotEquals(p1, p2); Assert.assertNotEquals(p1.hashCode(), p2.hashCode()); } @Test - @SmallTest - @UiThreadTest public void managerTest_updateIsPropagatedToAllObservers() { - final AtomicInteger numCalls = new AtomicInteger(0); + Consumer<SearchActivityPreferences> observer1 = mock(Consumer.class); + Consumer<SearchActivityPreferences> observer2 = mock(Consumer.class); + // Add 2 distinct listeners and confirm everybody gets called immediately with initial // values. - SearchActivityPreferencesManager.addObserver(prefs -> numCalls.incrementAndGet()); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 1); - SearchActivityPreferencesManager.addObserver(prefs -> numCalls.incrementAndGet()); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 2); + SearchActivityPreferencesManager.addObserver(observer1); + verify(observer1).accept(any()); + SearchActivityPreferencesManager.addObserver(observer2); + verify(observer1).accept(any()); + clearInvocations(observer1, observer2); // Perform an update and check the number of calls. - numCalls.set(0); - SearchActivityPreferencesManager.setCurrentlyLoadedPreferences( - new SearchActivityPreferences("Search Engine", "URL", false, true, true), false); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 2); + var newSettings = + new SearchActivityPreferences( + "Search Engine", new GURL("https://URL"), false, true, true); + SearchActivityPreferencesManager.setCurrentlyLoadedPreferences(newSettings, false); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + verify(observer1).accept(eq(newSettings)); + verify(observer2).accept(eq(newSettings)); + clearInvocations(observer1, observer2); // Add a new listener. - numCalls.set(0); - SearchActivityPreferencesManager.addObserver(prefs -> numCalls.incrementAndGet()); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 1); + Consumer<SearchActivityPreferences> observer3 = mock(Consumer.class); + SearchActivityPreferencesManager.addObserver(observer3); + verify(observer3).accept(eq(newSettings)); + clearInvocations(observer1, observer2, observer3); // Perform an update and check the number of calls. - numCalls.set(0); - SearchActivityPreferencesManager.setCurrentlyLoadedPreferences( - new SearchActivityPreferences("Search Engine", "URL", true, true, true), false); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 3); + newSettings = + new SearchActivityPreferences( + "Search Engine", new GURL("https://URL"), true, true, true); + SearchActivityPreferencesManager.setCurrentlyLoadedPreferences(newSettings, false); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + verify(observer1).accept(eq(newSettings)); + verify(observer2).accept(eq(newSettings)); + verify(observer3).accept(eq(newSettings)); + clearInvocations(observer1, observer2, observer3); // Finally, reset settings to safe defaults. All listeners should be notified. - numCalls.set(0); SearchActivityPreferencesManager.resetCachedValues(); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 3); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + verify(observer1).accept(any()); + verify(observer2).accept(any()); + verify(observer3).accept(any()); } @Test - @SmallTest - @UiThreadTest public void managerTest_eachObserverCanOnlyBeAddedOnce() { - final AtomicInteger numCalls = new AtomicInteger(0); - final Consumer<SearchActivityPreferences> listener = prefs -> numCalls.incrementAndGet(); + final Consumer<SearchActivityPreferences> listener1 = mock(Consumer.class); // Add same listener a few times. - SearchActivityPreferencesManager.addObserver(listener); - Assert.assertEquals(1, numCalls.get()); - SearchActivityPreferencesManager.addObserver(listener); - Assert.assertEquals(1, numCalls.get()); + SearchActivityPreferencesManager.addObserver(listener1); + verify(listener1).accept(any()); + clearInvocations(listener1); + + SearchActivityPreferencesManager.addObserver(listener1); + verify(listener1, never()).accept(any()); // Add a different listener. - SearchActivityPreferencesManager.addObserver(prefs -> numCalls.incrementAndGet()); - Assert.assertEquals(2, numCalls.get()); - SearchActivityPreferencesManager.addObserver(listener); - Assert.assertEquals(2, numCalls.get()); + Consumer<SearchActivityPreferences> listener2 = mock(Consumer.class); + SearchActivityPreferencesManager.addObserver(listener2); + verify(listener1, never()).accept(any()); + verify(listener2).accept(any()); + clearInvocations(listener1, listener2); + + SearchActivityPreferencesManager.addObserver(listener2); + SearchActivityPreferencesManager.addObserver(listener1); + verify(listener1, never()).accept(any()); + verify(listener2, never()).accept(any()); // Verify that we don't get excessive update notifications. - numCalls.set(0); SearchActivityPreferencesManager.setCurrentlyLoadedPreferences( - new SearchActivityPreferences("ABC", "abc.xyz", false, true, true), false); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 2); + new SearchActivityPreferences( + "ABC", new GURL("https://abc.xyz"), false, true, true), + false); + verify(listener1, never()).accept(any()); + verify(listener2, never()).accept(any()); + ShadowLooper.runUiThreadTasks(); + verify(listener1).accept(any()); + verify(listener2).accept(any()); + clearInvocations(listener1, listener2); // Finally, confirm reset. - numCalls.set(0); SearchActivityPreferencesManager.resetCachedValues(); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 2); + verify(listener1, never()).accept(any()); + verify(listener2, never()).accept(any()); + ShadowLooper.runUiThreadTasks(); + verify(listener1).accept(any()); + verify(listener2).accept(any()); } @Test - @SmallTest - @UiThreadTest public void managerTest_preferencesRetentionTest() { final SharedPreferencesManager manager = ChromeSharedPreferences.getInstance(); @@ -271,24 +343,29 @@ // Install receiver of the async pref update notification. // We expect the on-disk prefs to be already updated when this call is made. - final AtomicInteger numCalls = new AtomicInteger(0); - final Consumer<SearchActivityPreferences> listener = prefs -> numCalls.incrementAndGet(); + Consumer<SearchActivityPreferences> listener = mock(Consumer.class); SearchActivityPreferencesManager.addObserver(listener); - numCalls.set(0); + clearInvocations(listener); // Save settings to disk. - SearchActivityPreferencesManager.setCurrentlyLoadedPreferences( - new SearchActivityPreferences("Search Engine", "URL", false, true, true), true); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 1); + var persistedUrl = new GURL("https://URL"); + var preference = + new SearchActivityPreferences("Search Engine", persistedUrl, false, true, true); + SearchActivityPreferencesManager.setCurrentlyLoadedPreferences(preference, true); + // Should not be live right away - expect posted task. + verify(listener, never()).accept(any()); + ShadowLooper.runUiThreadTasks(); + verify(listener).accept(eq(preference)); // Note: we provide different default values than stored ones to make sure everything works. Assert.assertEquals( "Search Engine", manager.readString( SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME, "Engine Name Doesn't work")); - Assert.assertEquals( - "URL", - manager.readString(SEARCH_WIDGET_SEARCH_ENGINE_URL, "Engine URL Doesn't work")); + + GURL deserializedUrl = + GURL.deserialize(manager.readString(SEARCH_WIDGET_SEARCH_ENGINE_URL, "")); + Assert.assertEquals(persistedUrl, deserializedUrl); Assert.assertEquals( false, manager.readBoolean(SEARCH_WIDGET_IS_VOICE_SEARCH_AVAILABLE, true)); Assert.assertEquals( @@ -306,14 +383,11 @@ } @Test - @SmallTest - @UiThreadTest public void managerTest_earlyInitializationOfTemplateUrlService() { // Install event listener. - final AtomicInteger numCalls = new AtomicInteger(0); - final Consumer<SearchActivityPreferences> listener = prefs -> numCalls.incrementAndGet(); + Consumer<SearchActivityPreferences> listener = mock(Consumer.class); SearchActivityPreferencesManager.addObserver(listener); - numCalls.set(0); + clearInvocations(listener); verifyNoMoreInteractions(mTemplateUrlServiceMock); // Signal the Manager that Native Libraries are ready. @@ -335,24 +409,20 @@ // Confirm no data and no updates. Assert.assertNull(SearchActivityPreferencesManager.getCurrent().searchEngineName); - Assert.assertNull(SearchActivityPreferencesManager.getCurrent().searchEngineUrl); - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 0); + Assert.assertTrue(SearchActivityPreferencesManager.getCurrent().searchEngineUrl.isEmpty()); + ShadowLooper.runUiThreadTasksIncludingDelayedTasks(); + verify(listener, never()).accept(any()); } @Test - @SmallTest - @UiThreadTest public void managerTest_lateInitializationOfTemplateUrlService() { // Install event listener. - final AtomicInteger numCalls = new AtomicInteger(0); - final AtomicReference<SearchActivityPreferences> refPrefs = new AtomicReference<>(); - final Consumer<SearchActivityPreferences> listener = - prefs -> { - numCalls.incrementAndGet(); - refPrefs.set(prefs); - }; + Consumer<SearchActivityPreferences> listener = mock(Consumer.class); + ArgumentCaptor<SearchActivityPreferences> refPrefs = + ArgumentCaptor.forClass(SearchActivityPreferences.class); + SearchActivityPreferencesManager.addObserver(listener); - numCalls.set(0); + clearInvocations(listener); // Set up template url to have some data. doReturn("Cowabunga").when(mTemplateUrlMock).getShortName(); @@ -377,8 +447,104 @@ mTemplateUrlServiceLoadListener.onTemplateUrlServiceLoaded(); // Confirm data is available and update is pushed. - CriteriaHelper.pollUiThreadNested(() -> numCalls.get() == 1); - Assert.assertEquals("Cowabunga", refPrefs.get().searchEngineName); - Assert.assertEquals("https://www.cowabunga.com/", refPrefs.get().searchEngineUrl); + ShadowLooper.runUiThreadTasks(); + verify(listener).accept(refPrefs.capture()); + Assert.assertEquals("Cowabunga", refPrefs.getValue().searchEngineName); + Assert.assertEquals( + "https://www.cowabunga.com/", refPrefs.getValue().searchEngineUrl.getSpec()); + } + + @Test + public void initializeFromCache_withOldStyleUrl() { + final SharedPreferencesManager manager = ChromeSharedPreferences.getInstance(); + + manager.writeString(SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME, "Engine"); + manager.writeString(SEARCH_WIDGET_SEARCH_ENGINE_URL, "https://engine.com"); + + // Force re-read persisted data. + SearchActivityPreferencesManager.resetForTesting(); + SearchActivityPreferences data = SearchActivityPreferencesManager.getCurrent(); + + Assert.assertEquals("Engine", data.searchEngineName); + Assert.assertEquals("https://engine.com/", data.searchEngineUrl.getSpec()); + } + + @Test + public void initializeFromCache_withSerializedUrl() { + final SharedPreferencesManager manager = ChromeSharedPreferences.getInstance(); + + manager.writeString(SEARCH_WIDGET_SEARCH_ENGINE_SHORTNAME, "Engine"); + manager.writeString( + SEARCH_WIDGET_SEARCH_ENGINE_URL, new GURL("https://engine.com").serialize()); + + // Force re-read persisted data. + SearchActivityPreferencesManager.resetForTesting(); + SearchActivityPreferences data = SearchActivityPreferencesManager.getCurrent(); + + Assert.assertEquals("Engine", data.searchEngineName); + Assert.assertEquals("https://engine.com/", data.searchEngineUrl.getSpec()); + } + + @Test + public void updateFeatureAvailability() { + ShadowLensController.sIsAvailable = true; + ShadowVoiceRecognitionUtil.sIsAvailable = true; + ShadowIncognitoUtils.sIsAvailable = true; + + SearchActivityPreferencesManager.updateFeatureAvailability( + ContextUtils.getApplicationContext(), null); + var data = SearchActivityPreferencesManager.getCurrent(); + Assert.assertTrue(data.googleLensAvailable); + Assert.assertTrue(data.voiceSearchAvailable); + Assert.assertTrue(data.incognitoAvailable); + + // Disable Lens. + ShadowLensController.sIsAvailable = false; + SearchActivityPreferencesManager.updateFeatureAvailability( + ContextUtils.getApplicationContext(), null); + data = SearchActivityPreferencesManager.getCurrent(); + Assert.assertFalse(data.googleLensAvailable); + Assert.assertTrue(data.voiceSearchAvailable); + Assert.assertTrue(data.incognitoAvailable); + + // Disable Voice. + ShadowVoiceRecognitionUtil.sIsAvailable = false; + SearchActivityPreferencesManager.updateFeatureAvailability( + ContextUtils.getApplicationContext(), null); + data = SearchActivityPreferencesManager.getCurrent(); + Assert.assertFalse(data.googleLensAvailable); + Assert.assertFalse(data.voiceSearchAvailable); + Assert.assertTrue(data.incognitoAvailable); + + // Disable Incognito. + ShadowIncognitoUtils.sIsAvailable = false; + SearchActivityPreferencesManager.updateFeatureAvailability( + ContextUtils.getApplicationContext(), null); + data = SearchActivityPreferencesManager.getCurrent(); + Assert.assertFalse(data.googleLensAvailable); + Assert.assertFalse(data.voiceSearchAvailable); + Assert.assertFalse(data.incognitoAvailable); + } + + @Test + public void onTemplateUrlServiceChanged_retrieveNewEngineNameAndUrl() { + var oldData = SearchActivityPreferencesManager.getCurrent(); + + // Simulate change. + doReturn("Engine").when(mTemplateUrlMock).getShortName(); + doReturn("keyword").when(mTemplateUrlMock).getKeyword(); + doReturn("https://www.engine.com/some/path?with=query") + .when(mTemplateUrlServiceMock) + .getSearchEngineUrlFromTemplateUrl(eq("keyword")); + doReturn(mTemplateUrlMock) + .when(mTemplateUrlServiceMock) + .getDefaultSearchEngineTemplateUrl(); + SearchActivityPreferencesManager.get().onTemplateURLServiceChanged(); + + var newData = SearchActivityPreferencesManager.getCurrent(); + Assert.assertNotEquals(oldData, newData); + Assert.assertEquals("Engine", newData.searchEngineName); + // We only expect origin: no path, no query. + Assert.assertEquals("https://www.engine.com/", newData.searchEngineUrl.getSpec()); } }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 261cf809..bfef3ea 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -208,9 +208,6 @@ <message name="IDS_COOKIE_CONTROLS_IPH_MESSAGE" desc="In-context Product Help - Appears right under the page info icon to highlight the Cookie Controls entrypoint."> Site not working? Third-party cookies are blocked </message> - <message name="IDS_COOKIE_CONTROLS_REMINDER_IPH_MESSAGE" desc="In-context Product Help - Appears right under the page info icon to highlight the Cookie Controls entrypoint. This message is a reminder."> - Site not working? Try temporarily allowing third-party cookies - </message> <!-- Main Preferences --> <message name="IDS_PREFS_SECTION_BASICS" desc='Title of "Basics" section of preferences. [CHAR_LIMIT=32]'>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_COOKIE_CONTROLS_REMINDER_IPH_MESSAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_COOKIE_CONTROLS_REMINDER_IPH_MESSAGE.png.sha1 deleted file mode 100644 index 41254fd..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_COOKIE_CONTROLS_REMINDER_IPH_MESSAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9b3327daa12381fbcea5b992b8094fad6fa37099 \ No newline at end of file
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc index acd39c5..d38c1826 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
@@ -16,6 +16,7 @@ #include "components/sessions/content/content_live_tab.h" #include "components/sessions/content/content_serialized_navigation_builder.h" #include "components/sessions/core/session_types.h" +#include "components/sessions/core/tab_restore_types.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" #include "content/public/browser/browser_context.h" @@ -136,24 +137,15 @@ } sessions::LiveTab* AndroidLiveTabContext::AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, + const sessions::tab_restore::Tab& tab, int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) { + bool select) { Profile* profile = tab_model_->GetProfile(); // Prepare navigation history. std::vector<std::unique_ptr<content::NavigationEntry>> nav_entries = sessions::ContentSerializedNavigationBuilder::ToNavigationEntries( - navigations, profile); + tab.navigations, profile); // Restore web contents with navigation history. This is used for background // restore so start without a renderer. @@ -164,8 +156,9 @@ std::unique_ptr<content::WebContents> web_contents = content::WebContents::Create(params); content::WebContents* raw_web_contents = web_contents.get(); - web_contents->GetController().Restore( - selected_navigation, content::RestoreType::kRestored, &nav_entries); + web_contents->GetController().Restore(tab.normalized_navigation_index(), + content::RestoreType::kRestored, + &nav_entries); // Create new tab. Ownership is passed into java, which in turn creates a new // TabAndroid instance to own the WebContents. @@ -178,17 +171,11 @@ } sessions::LiveTab* AndroidLiveTabContext::ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) { + const sessions::tab_restore::Tab& tab) { // Prepare navigation history. sessions::SessionTab session_tab; - session_tab.current_navigation_index = selected_navigation; - session_tab.navigations = navigations; + session_tab.current_navigation_index = tab.normalized_navigation_index(); + session_tab.navigations = tab.navigations; // This is called only on replacement of the current tab. content::WebContents* web_contents = tab_model_->GetActiveWebContents();
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.h b/chrome/browser/ui/android/tab_model/android_live_tab_context.h index efa83eccb..6a12ce6c8 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context.h +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "components/sessions/core/live_tab_context.h" +#include "components/sessions/core/tab_restore_types.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" @@ -60,27 +61,11 @@ const gfx::Rect GetRestoredBounds() const override; ui::WindowShowState GetRestoredState() const override; std::string GetWorkspace() const override; - sessions::LiveTab* AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* storage_namespace, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) override; + sessions::LiveTab* AddRestoredTab(const sessions::tab_restore::Tab& tab, + int tab_index, + bool select) override; sessions::LiveTab* ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) override; + const sessions::tab_restore::Tab&) override; void CloseTab() override; static LiveTabContext* FindContextForWebContents(
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.cc b/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.cc index 817a17ec..85056cb 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.cc +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/android/tab_android.h" #include "chrome/browser/ui/android/tab_model/tab_model.h" #include "components/sessions/content/content_live_tab.h" +#include "components/sessions/core/tab_restore_types.h" AndroidLiveTabContextCloseWrapper::AndroidLiveTabContextCloseWrapper( TabModel* tab_model, @@ -90,28 +91,17 @@ } sessions::LiveTab* AndroidLiveTabContextRestoreWrapper::AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, + const sessions::tab_restore::Tab& tab, int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* storage_namespace, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) { - auto* live_tab = AndroidLiveTabContext::AddRestoredTab( - navigations, tab_index, selected_navigation, extension_app_id, group, - group_visual_data, select, pin, storage_namespace, user_agent_override, - extra_data, tab_id); - if (group) { - TabAndroid* tab = TabAndroid::FromWebContents( + bool select) { + auto* live_tab = + AndroidLiveTabContext::AddRestoredTab(tab, tab_index, select); + if (tab.group) { + TabAndroid* restored_tab = TabAndroid::FromWebContents( static_cast<sessions::ContentLiveTab*>(live_tab)->web_contents()); - DCHECK(tab); - tab_groups_[*group].visual_data = group_visual_data; - tab_groups_[*group].tab_ids.push_back(tab->GetAndroidId()); + DCHECK(restored_tab); + tab_groups_[*tab.group].visual_data = *tab.group_visual_data; + tab_groups_[*tab.group].tab_ids.push_back(restored_tab->GetAndroidId()); } return live_tab; }
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.h b/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.h index 38ab608..565767ef 100644 --- a/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.h +++ b/chrome/browser/ui/android/tab_model/android_live_tab_context_wrapper.h
@@ -15,6 +15,7 @@ #include "chrome/browser/tab/web_contents_state.h" #include "chrome/browser/ui/android/tab_model/android_live_tab_context.h" #include "components/sessions/core/live_tab.h" +#include "components/sessions/core/tab_restore_types.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" @@ -127,19 +128,9 @@ void SetVisualDataForGroup( const tab_groups::TabGroupId& group, const tab_groups::TabGroupVisualData& visual_data) override; - sessions::LiveTab* AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* storage_namespace, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) override; + sessions::LiveTab* AddRestoredTab(const sessions::tab_restore::Tab& tab, + int tab_index, + bool select) override; // Returns the TabGroup data aggregated via AddRestoredTab. const std::map<tab_groups::TabGroupId, TabGroup>& GetTabGroups();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java index 0741906..ca83602 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -9,6 +9,7 @@ import android.view.View; import android.view.ViewGroup; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import org.chromium.base.supplier.ObservableSupplier; @@ -41,6 +42,8 @@ /** Interface for the BottomControls component to hide and show itself. */ public interface BottomControlsVisibilityController { void setBottomControlsVisible(boolean isVisible); + + void setBottomControlsColor(@ColorInt int color); } /** The mediator that handles events from outside the bottom controls. */ @@ -132,7 +135,19 @@ if (mContentDelegate != null) { mContentDelegate.initializeWithNative( - activity, mMediator::setBottomControlsVisible, root::onModelTokenChange); + activity, + new BottomControlsVisibilityController() { + @Override + public void setBottomControlsVisible(boolean isVisible) { + mMediator.setBottomControlsVisible(isVisible); + } + + @Override + public void setBottomControlsColor(int color) { + mMediator.setBottomControlsColor(color); + } + }, + root::onModelTokenChange); } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java index 843b03d..0ef4e04 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsMediator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.toolbar.bottom; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import org.chromium.base.CallbackController; @@ -60,6 +61,9 @@ /** The bottom controls visibility. */ private boolean mIsBottomControlsVisible; + /** The background color for the bottom controls. */ + private @ColorInt int mBottomControlsColor; + /** Whether any overlay panel is showing. */ private boolean mIsOverlayPanelShowing; @@ -144,6 +148,10 @@ updateAndroidViewVisibility(); } + void setBottomControlsColor(@ColorInt int color) { + mBottomControlsColor = color; + } + /** Clean up anything that needs to be when the bottom controls component is destroyed. */ void destroy() { mCallbackController.destroy(); @@ -186,6 +194,11 @@ if (mReadAloudRestoringSupplier.get()) { mModel.set(BottomControlsProperties.ANDROID_VIEW_TRANSLATE_Y, -bottomControlsMinHeight); } + // A min height greater than 0 suggests the presence of some other UI component underneath + // the bottom controls. + if (bottomControlsMinHeight == 0) { + mBrowserControlsSizer.notifyBackgroundColor(mBottomControlsColor); + } } @Override
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl.cc b/chrome/browser/ui/ash/picker/picker_client_impl.cc index a4b19aef..9305233e 100644 --- a/chrome/browser/ui/ash/picker/picker_client_impl.cc +++ b/chrome/browser/ui/ash/picker/picker_client_impl.cc
@@ -431,11 +431,13 @@ } } -void PickerClientImpl::ShowEditor() { +void PickerClientImpl::ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text) { ash::input_method::EditorMediator* editor_mediator = GetEditorMediator(profile_); if (editor_mediator != nullptr) { - editor_mediator->HandleTrigger(); + editor_mediator->HandleTrigger(std::move(preset_query_id), + std::move(freeform_text)); } }
diff --git a/chrome/browser/ui/ash/picker/picker_client_impl.h b/chrome/browser/ui/ash/picker/picker_client_impl.h index 5addfc7..7494b12 100644 --- a/chrome/browser/ui/ash/picker/picker_client_impl.h +++ b/chrome/browser/ui/ash/picker/picker_client_impl.h
@@ -123,7 +123,8 @@ std::unique_ptr<app_list::SearchProvider> CreateSearchProviderForCategory( ash::PickerCategory category); - void ShowEditor(); + void ShowEditor(std::optional<std::string> preset_query_id, + std::optional<std::string> freeform_text); raw_ptr<ash::PickerController> controller_ = nullptr; raw_ptr<Profile> profile_ = nullptr;
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc index 4d615dd..cb48a7ef 100644 --- a/chrome/browser/ui/ash/session_controller_client_impl.cc +++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -48,7 +48,7 @@ #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "components/supervised_user/core/browser/supervised_user_service.h" -#include "components/user_manager/multi_user/multi_user_sign_in_policy_controller.h" +#include "components/user_manager/multi_user/multi_user_sign_in_policy.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager_pref_names.h" #include "components/user_manager/user_type.h" @@ -454,8 +454,7 @@ if (user_manager->GetUsersAllowedForMultiProfile().empty()) return ash::AddUserSessionPolicy::ERROR_NO_ELIGIBLE_USERS; - if (user_manager->GetMultiUserSignInPolicyController() - ->GetPrimaryUserPolicy() == + if (user_manager::GetMultiUserSignInPolicy(user_manager->GetPrimaryUser()) == user_manager::MultiUserSignInPolicy::kNotAllowed) { return ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER; }
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.cc new file mode 100644 index 0000000..1c4a6fe --- /dev/null +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.cc
@@ -0,0 +1,49 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.h" + +#include "ash/public/cpp/shelf_item.h" +#include "ash/public/cpp/shelf_model.h" +#include "base/metrics/histogram_functions.h" +#include "chrome/browser/apps/app_service/metrics/app_service_metrics.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h" + +ChromeShelfMetricsProvider::ChromeShelfMetricsProvider() = default; + +ChromeShelfMetricsProvider::~ChromeShelfMetricsProvider() = default; + +void ChromeShelfMetricsProvider::ProvideCurrentSessionData( + metrics::ChromeUserMetricsExtension*) { + const ChromeShelfController* controller = ChromeShelfController::instance(); + if (!controller) { + return; + } + + // The `ChromeShelfController` is a singleton but it's attached profile may + // change at runtime in a multi-profile setting. Only record metrics if the + // `controller` has attached to the active profile and is not in a state of + // transition. Note that this will become obsolete with Lacros. + const Profile* profile = ProfileManager::GetActiveUserProfile(); + if (!profile || controller->profile() != profile) { + return; + } + + ash::ShelfModel* model = controller->shelf_model(); + if (!model) { + return; + } + + for (const ash::ShelfItem& item : model->items()) { + if (item.type == ash::TYPE_PINNED_APP || + item.type == ash::TYPE_BROWSER_SHORTCUT) { + if (const std::optional<apps::DefaultAppName> default_app_name = + apps::AppIdToName(item.id.app_id)) { + base::UmaHistogramEnumeration("Ash.Shelf.DefaultApps.Pinned", + default_app_name.value()); + } + } + } +}
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.h b/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.h new file mode 100644 index 0000000..95d457a --- /dev/null +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_metrics_provider.h
@@ -0,0 +1,25 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_SHELF_CHROME_SHELF_METRICS_PROVIDER_H_ +#define CHROME_BROWSER_UI_ASH_SHELF_CHROME_SHELF_METRICS_PROVIDER_H_ + +#include "components/metrics/metrics_provider.h" + +// A provider which records shelf related metrics such as which default apps are +// pinned to the shelf. +class ChromeShelfMetricsProvider : public metrics::MetricsProvider { + public: + ChromeShelfMetricsProvider(); + ChromeShelfMetricsProvider(const ChromeShelfMetricsProvider&) = delete; + ChromeShelfMetricsProvider& operator=(const ChromeShelfMetricsProvider&) = + delete; + ~ChromeShelfMetricsProvider() override; + + private: + // metrics::MetricsProvider: + void ProvideCurrentSessionData(metrics::ChromeUserMetricsExtension*) override; +}; + +#endif // CHROME_BROWSER_UI_ASH_SHELF_CHROME_SHELF_METRICS_PROVIDER_H_
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc index cfa7367..13b6893d1 100644 --- a/chrome/browser/ui/browser_live_tab_context.cc +++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -195,43 +195,36 @@ } sessions::LiveTab* BrowserLiveTabContext::AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, + const sessions::tab_restore::Tab& tab, int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) { + bool select) { SessionStorageNamespace* storage_namespace = - tab_platform_data + tab.platform_data ? static_cast<const sessions::ContentPlatformSpecificTabData*>( - tab_platform_data) + tab.platform_data.get()) ->session_storage_namespace() : nullptr; TabGroupModel* group_model = browser_->tab_strip_model()->group_model(); - const bool first_tab_in_group = group_model && group.has_value() && - !group_model->ContainsTabGroup(group.value()); + const bool first_tab_in_group = + group_model && tab.group.has_value() && + !group_model->ContainsTabGroup(tab.group.value()); + WebContents* web_contents = nullptr; - web_contents = chrome::AddRestoredTab( - browser_, navigations, tab_index, selected_navigation, extension_app_id, - group, select, pin, base::TimeTicks(), storage_namespace, - user_agent_override, extra_data, false /* from_session_restore */); - + web_contents = chrome::AddRestoredTab( + browser_, tab.navigations, tab_index, tab.normalized_navigation_index(), + tab.extension_app_id, tab.group, select, tab.pinned, base::TimeTicks(), + storage_namespace, tab.user_agent_override, tab.extra_data, + false /* from_session_restore */); // Only update the metadata if the group doesn't already exist since the // existing group has the latest metadata, which may have changed from the // time the tab was closed. if (first_tab_in_group) { const tab_groups::TabGroupVisualData new_data( - group_visual_data.title(), group_visual_data.color(), false); - group_model->GetTabGroup(group.value())->SetVisualData(new_data); + tab.group_visual_data->title(), tab.group_visual_data->color(), false); + group_model->GetTabGroup(tab.group.value())->SetVisualData(new_data); } #if BUILDFLAG(ENABLE_SESSION_SERVICE) @@ -247,8 +240,9 @@ DCHECK(!web_contents->IsLoading()); } std::vector<TabLoader::RestoredTab> restored_tabs; - restored_tabs.emplace_back(web_contents, is_active, !extension_app_id.empty(), - pin, group); + restored_tabs.emplace_back(web_contents, is_active, + !tab.extension_app_id.empty(), tab.pinned, + tab.group); TabLoader::RestoreTabs(restored_tabs, base::TimeTicks::Now()); #else // BUILDFLAG(ENABLE_SESSION_SERVICE) // Load the tab manually if there is no TabLoader. @@ -259,13 +253,9 @@ } sessions::LiveTab* BrowserLiveTabContext::ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) { + const sessions::tab_restore::Tab& tab) { + const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data = + tab.platform_data.get(); SessionStorageNamespace* storage_namespace = tab_platform_data ? static_cast<const sessions::ContentPlatformSpecificTabData*>( @@ -274,9 +264,9 @@ : nullptr; WebContents* web_contents = chrome::ReplaceRestoredTab( - browser_, navigations, selected_navigation, extension_app_id, - storage_namespace, user_agent_override, extra_data, - false /* from_session_restore */); + browser_, tab.navigations, tab.normalized_navigation_index(), + tab.extension_app_id, storage_namespace, tab.user_agent_override, + tab.extra_data, false /* from_session_restore */); return sessions::ContentLiveTab::GetForWebContents(web_contents); }
diff --git a/chrome/browser/ui/browser_live_tab_context.h b/chrome/browser/ui/browser_live_tab_context.h index 5b8c4a5..d9299eaf 100644 --- a/chrome/browser/ui/browser_live_tab_context.h +++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -67,27 +67,11 @@ const gfx::Rect GetRestoredBounds() const override; ui::WindowShowState GetRestoredState() const override; std::string GetWorkspace() const override; - sessions::LiveTab* AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* storage_namespace, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) override; + sessions::LiveTab* AddRestoredTab(const sessions::tab_restore::Tab& tab, + int tab_index, + bool select) override; sessions::LiveTab* ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) override; + const sessions::tab_restore::Tab& tab) override; void CloseTab() override; // see Browser::Create
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.cc b/chrome/browser/ui/lens/lens_overlay_controller.cc index 057317e..6cda0e2 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller.cc
@@ -183,6 +183,8 @@ weak_factory_.GetWeakPtr()), base::BindRepeating(&LensOverlayController::HandleInteractionDataResponse, weak_factory_.GetWeakPtr()), + base::BindRepeating(&LensOverlayController::HandleThumbnailCreated, + weak_factory_.GetWeakPtr()), variations_client_, identity_manager_); state_ = State::kScreenshot; @@ -246,6 +248,9 @@ scoped_tab_modal_ui_.reset(); latest_interaction_response_.Clear(); selected_region_.reset(); + pending_side_panel_url_.reset(); + pending_text_query_.reset(); + pending_thumbnail_uri_.reset(); last_search_box_text_.reset(); additional_search_query_params_.clear(); // In the future we may want a hibernate state. In this case we would stop @@ -375,11 +380,13 @@ lens::LensOverlayFullImageResponseCallback full_image_callback, lens::LensOverlayUrlResponseCallback url_callback, lens::LensOverlayInteractionResponseCallback interaction_data_callback, + lens::LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager) { return std::make_unique<lens::LensOverlayQueryController>( std::move(full_image_callback), std::move(url_callback), - std::move(interaction_data_callback), variations_client, + std::move(interaction_data_callback), + std::move(thumbnail_created_callback), variations_client, identity_manager); } @@ -450,7 +457,7 @@ return; } current_screenshot_data_uri_ = - webui::MakeDataURIForImage(data->data(), "jpeg"); + webui::MakeDataURIForImage(data->as_vector(), "jpeg"); ShowOverlayWidget(); @@ -576,16 +583,21 @@ } void LensOverlayController::OnPageBound() { - // If ths side panel closes before the remote gets bound, searchbox_handler_ + // If the side panel closes before the remote gets bound, searchbox_handler_ // could become unset. Verify it is set before sending to the side panel. - if (!pending_text_query_.has_value() || !searchbox_handler_ || - !searchbox_handler_->IsRemoteBound()) { + if (!searchbox_handler_ || !searchbox_handler_->IsRemoteBound()) { return; } - // TODO(b/333425452): Pass thumbnail to searchbox. + // Send any pending inputs for the searchbox. - searchbox_handler_->SetInputText(*pending_text_query_); - pending_text_query_.reset(); + if (pending_text_query_.has_value()) { + searchbox_handler_->SetInputText(*pending_text_query_); + pending_text_query_.reset(); + } + if (pending_thumbnail_uri_.has_value()) { + searchbox_handler_->SetThumbnail(*pending_thumbnail_uri_); + pending_thumbnail_uri_.reset(); + } } void LensOverlayController::TabForegrounded(tabs::TabInterface* tab) {} @@ -658,7 +670,7 @@ searchbox_handler_->SetInputText(query); } else { // If the side panel was not bound at the time of request, we store the - // query as pending to load results on bind. + // query as pending to send it to the searchbox on bind. pending_text_query_ = query; } @@ -714,3 +726,17 @@ lens::proto::LensOverlayInteractionResponse response) { latest_interaction_response_ = response; } + +void LensOverlayController::HandleThumbnailCreated( + const std::string& thumbnail_bytes) { + const std::string data_uri = webui::MakeDataURIForImage( + base::as_bytes(base::make_span(thumbnail_bytes)), "jpeg"); + + if (searchbox_handler_ && searchbox_handler_->IsRemoteBound()) { + searchbox_handler_->SetThumbnail(data_uri); + } else { + // If the side panel was not bound at the time of request, we store the + // thumbnail as pending to send it to the searchbox on bind. + pending_thumbnail_uri_ = data_uri; + } +}
diff --git a/chrome/browser/ui/lens/lens_overlay_controller.h b/chrome/browser/ui/lens/lens_overlay_controller.h index 8b6147a7..2f982951 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller.h +++ b/chrome/browser/ui/lens/lens_overlay_controller.h
@@ -193,6 +193,7 @@ lens::LensOverlayFullImageResponseCallback full_image_callback, lens::LensOverlayUrlResponseCallback url_callback, lens::LensOverlayInteractionResponseCallback interaction_data_callback, + lens::LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager); @@ -274,6 +275,9 @@ void HandleInteractionDataResponse( lens::proto::LensOverlayInteractionResponse response); + // Handles the creation of a new thumbnail based on the user selection. + void HandleThumbnailCreated(const std::string& thumbnail_bytes); + // Owns this class. raw_ptr<tabs::TabInterface> tab_; @@ -303,6 +307,10 @@ // panel is not bound at the time of a text request. std::optional<std::string> pending_text_query_ = std::nullopt; + // A pending thumbnail URI to be loaded in the side panel. Needed when the + // side panel is not bound at the time of a region request. + std::optional<std::string> pending_thumbnail_uri_ = std::nullopt; + // The last search box text, used in conjunction with the current region // to construct Lens requests. std::optional<std::string> last_search_box_text_ = std::nullopt;
diff --git a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc index c458ae0..af95bebe 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
@@ -52,7 +52,7 @@ }) )"; -constexpr char kCheckSidePanelLoadedScript[] = +constexpr char kCheckSidePanelResultsLoadedScript[] = "(function() {const root = " "document.getElementsByTagName('lens-side-panel-app')[0].shadowRoot; " "const iframeSrcLoaded = " @@ -61,6 +61,14 @@ " root.getElementById('realbox').shadowRoot.getElementById('input').value " " === $1; return iframeSrcLoaded && searchboxInputLoaded;})();"; +constexpr char kCheckSidePanelThumbnailLoadedScript[] = + "(function() {const appRoot = " + "document.getElementsByTagName('lens-side-panel-app')[0].shadowRoot;" + "const realboxRoot = appRoot.getElementById('realbox').shadowRoot;" + "const thumbnailRoot = realboxRoot.getElementById('thumbnail').shadowRoot;" + "const imageSrc = thumbnailRoot.getElementById('image').src;" + "return imageSrc.startsWith('data:image/jpeg');})();"; + constexpr char kTestSuggestSignals[] = "suggest_signals"; const lens::mojom::GeometryPtr kTestGeometry = @@ -108,11 +116,13 @@ lens::LensOverlayFullImageResponseCallback full_image_callback, lens::LensOverlayUrlResponseCallback url_callback, lens::LensOverlayInteractionResponseCallback interaction_data_callback, + lens::LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager) : LensOverlayQueryController(full_image_callback, url_callback, interaction_data_callback, + thumbnail_created_callback, variations_client, identity_manager) {} @@ -146,11 +156,12 @@ lens::LensOverlayFullImageResponseCallback full_image_callback, lens::LensOverlayUrlResponseCallback url_callback, lens::LensOverlayInteractionResponseCallback interaction_data_callback, + lens::LensOverlayThumbnailCreatedCallback thumbnail_created_callback, variations::VariationsClient* variations_client, signin::IdentityManager* identity_manager) override { return std::make_unique<LensOverlayQueryControllerFake>( full_image_callback, url_callback, interaction_data_callback, - variations_client, identity_manager); + thumbnail_created_callback, variations_client, identity_manager); } void BindOverlay(mojo::PendingReceiver<lens::mojom::LensPageHandler> receiver, @@ -419,6 +430,14 @@ ASSERT_TRUE(coordinator->IsSidePanelShowing()); EXPECT_EQ(coordinator->GetCurrentEntryId(), SidePanelEntry::Id::kLensOverlayResults); + + // Verify that the side panel searchbox displays a thumbnail. + ASSERT_TRUE(base::test::RunUntil([&]() { + return true == + content::EvalJs( + controller->GetSidePanelWebContentsForTesting(), + content::JsReplace(kCheckSidePanelThumbnailLoadedScript)); + })); } // TODO(b/335028577): Test flaky on Mac. @@ -461,9 +480,9 @@ // Verify that the side panel displays our query. ASSERT_TRUE(base::test::RunUntil([&]() { return true == - content::EvalJs( - controller->GetSidePanelWebContentsForTesting(), - content::JsReplace(kCheckSidePanelLoadedScript, text_query)); + content::EvalJs(controller->GetSidePanelWebContentsForTesting(), + content::JsReplace( + kCheckSidePanelResultsLoadedScript, text_query)); })); }
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc index 24ecde6..332ae48f 100644 --- a/chrome/browser/ui/tab_contents/core_tab_helper.cc +++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -141,12 +141,10 @@ // Get the front and end of the image bytes in order to store them in the // search_args to be sent as part of the PostContent in the request - size_t image_bytes_size = image.As1xPNGBytes()->size(); - const unsigned char* image_bytes_begin = image.As1xPNGBytes()->front(); - const unsigned char* image_bytes_end = image_bytes_begin + image_bytes_size; content_type = "image/png"; image_format = lens::mojom::ImageFormat::PNG; - data.assign(image_bytes_begin, image_bytes_end); + auto bytes = image.As1xPNGBytes(); + data.assign(bytes->begin(), bytes->end()); return data; }
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 8af12dd7..81c4d59 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -130,6 +130,7 @@ #include "components/download/content/factory/navigation_monitor_factory.h" #include "components/download/content/public/download_navigation_observer.h" #include "components/feed/buildflags.h" +#include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h" #include "components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.h" #include "components/history/content/browser/web_contents_top_sites_observer.h" #include "components/history/core/browser/top_sites.h" @@ -396,8 +397,8 @@ FileSystemAccessPermissionRequestManager::CreateForWebContents(web_contents); FileSystemAccessTabHelper::CreateForWebContents(web_contents); FindBarState::ConfigureWebContents(web_contents); - if (base::FeatureList::IsEnabled( - features::kEnableFingerprintingProtectionBlocklist)) { + if (base::FeatureList::IsEnabled(fingerprinting_protection_filter::features:: + kEnableFingerprintingProtectionFilter)) { fingerprinting_protection_filter:: FingerprintingProtectionWebContentsHelper::CreateForWebContents( web_contents);
diff --git a/chrome/browser/ui/tabs/pinned_tab_collection.cc b/chrome/browser/ui/tabs/pinned_tab_collection.cc index 7347526..40f7083 100644 --- a/chrome/browser/ui/tabs/pinned_tab_collection.cc +++ b/chrome/browser/ui/tabs/pinned_tab_collection.cc
@@ -54,7 +54,7 @@ } std::optional<size_t> PinnedTabCollection::GetIndexOfTabRecursive( - TabModel* tab_model) const { + const TabModel* tab_model) const { return impl_->GetIndexOfTab(tab_model); }
diff --git a/chrome/browser/ui/tabs/pinned_tab_collection.h b/chrome/browser/ui/tabs/pinned_tab_collection.h index 9c07c3f..c9401c2e 100644 --- a/chrome/browser/ui/tabs/pinned_tab_collection.h +++ b/chrome/browser/ui/tabs/pinned_tab_collection.h
@@ -51,7 +51,7 @@ // This is non-recursive for pinned tab collection as it does not contain // another collection. std::optional<size_t> GetIndexOfTabRecursive( - TabModel* tab_model) const override; + const TabModel* tab_model) const override; // This is nullopt as pinned tab collection does not contain another // collection.
diff --git a/chrome/browser/ui/tabs/tab_collection.h b/chrome/browser/ui/tabs/tab_collection.h index 89c3aa98..d049155 100644 --- a/chrome/browser/ui/tabs/tab_collection.h +++ b/chrome/browser/ui/tabs/tab_collection.h
@@ -40,7 +40,7 @@ // Recursively get the index of the tab_model among all the leaf tab_models. virtual std::optional<size_t> GetIndexOfTabRecursive( - TabModel* tab_model) const = 0; + const TabModel* tab_model) const = 0; // Non-recursively get the index of a collection. virtual std::optional<size_t> GetIndexOfCollection( @@ -75,7 +75,7 @@ protected: // Returns the pass key to be used by derived classes as operations such as // setting the parent of a tab can only be performed by a `TabCollection`. - base::PassKey<TabCollection> GetPassKey() { + base::PassKey<TabCollection> GetPassKey() const { return base::PassKey<TabCollection>(); }
diff --git a/chrome/browser/ui/tabs/tab_collection_storage.cc b/chrome/browser/ui/tabs/tab_collection_storage.cc index f5f83d6..ad72bfd 100644 --- a/chrome/browser/ui/tabs/tab_collection_storage.cc +++ b/chrome/browser/ui/tabs/tab_collection_storage.cc
@@ -114,7 +114,7 @@ } std::optional<size_t> TabCollectionStorage::GetIndexOfTab( - TabModel* tab_model) const { + const TabModel* const tab_model) const { const auto it = std::find_if( children_.begin(), children_.end(), [tab_model](const auto& child) { return std::holds_alternative<std::unique_ptr<TabModel>>(child) &&
diff --git a/chrome/browser/ui/tabs/tab_collection_storage.h b/chrome/browser/ui/tabs/tab_collection_storage.h index 03959dc..2f6d7a8 100644 --- a/chrome/browser/ui/tabs/tab_collection_storage.h +++ b/chrome/browser/ui/tabs/tab_collection_storage.h
@@ -78,7 +78,7 @@ // Returns the index of the `tab_model` in `children_`. It returns a nullopt // if the `tab_model` is not present in the `children_`. - std::optional<size_t> GetIndexOfTab(TabModel* tab_model) const; + std::optional<size_t> GetIndexOfTab(const TabModel* tab_model) const; // Returns the tab at a direct index if the child at the direct index is a // tab.
diff --git a/chrome/browser/ui/tabs/tab_collection_unittest.cc b/chrome/browser/ui/tabs/tab_collection_unittest.cc index 9ac8f7a6..182342a 100644 --- a/chrome/browser/ui/tabs/tab_collection_unittest.cc +++ b/chrome/browser/ui/tabs/tab_collection_unittest.cc
@@ -334,6 +334,13 @@ EXPECT_EQ(GetCollection()->ChildCount(), 5ul); EXPECT_EQ(GetCollection()->TabCountRecursive(), 6ul); + + EXPECT_EQ(GetCollection()->GetDirectChildIndexOfCollectionContainingTab( + GetCollection()->GetTabAtIndexRecursive(1)), + 1ul); + EXPECT_EQ(GetCollection()->GetDirectChildIndexOfCollectionContainingTab( + GetCollection()->GetTabAtIndexRecursive(3)), + 2ul); } private:
diff --git a/chrome/browser/ui/tabs/tab_group_tab_collection.cc b/chrome/browser/ui/tabs/tab_group_tab_collection.cc index 8260f8c..1c82aaee 100644 --- a/chrome/browser/ui/tabs/tab_group_tab_collection.cc +++ b/chrome/browser/ui/tabs/tab_group_tab_collection.cc
@@ -55,7 +55,7 @@ } std::optional<size_t> TabGroupTabCollection::GetIndexOfTabRecursive( - TabModel* tab_model) const { + const TabModel* tab_model) const { return impl_->GetIndexOfTab(tab_model); }
diff --git a/chrome/browser/ui/tabs/tab_group_tab_collection.h b/chrome/browser/ui/tabs/tab_group_tab_collection.h index 70df7902..da6486d2 100644 --- a/chrome/browser/ui/tabs/tab_group_tab_collection.h +++ b/chrome/browser/ui/tabs/tab_group_tab_collection.h
@@ -59,7 +59,7 @@ // This is non-recursive for grouped tab collection as it does not contain // another collection. std::optional<size_t> GetIndexOfTabRecursive( - TabModel* tab_model) const override; + const TabModel* tab_model) const override; // This is nullopt as grouped tab collection does not contain another // collection.
diff --git a/chrome/browser/ui/tabs/tab_strip_collection.cc b/chrome/browser/ui/tabs/tab_strip_collection.cc index b5ba2b1a..eb68078 100644 --- a/chrome/browser/ui/tabs/tab_strip_collection.cc +++ b/chrome/browser/ui/tabs/tab_strip_collection.cc
@@ -72,7 +72,7 @@ } std::optional<size_t> TabStripCollection::GetIndexOfTabRecursive( - TabModel* tab_model) const { + const TabModel* tab_model) const { // Check if the tab is present in the pinned collection first and return the // index if it is present. std::optional<size_t> pinned_index =
diff --git a/chrome/browser/ui/tabs/tab_strip_collection.h b/chrome/browser/ui/tabs/tab_strip_collection.h index dacb37e..b3c751b9 100644 --- a/chrome/browser/ui/tabs/tab_strip_collection.h +++ b/chrome/browser/ui/tabs/tab_strip_collection.h
@@ -64,7 +64,7 @@ // unpinned collection. bool ContainsCollection(TabCollection* collection) const override; std::optional<size_t> GetIndexOfTabRecursive( - TabModel* tab_model) const override; + const TabModel* tab_model) const override; std::optional<size_t> GetIndexOfCollection( TabCollection* collection) const override; // Tabs and Collections are not allowed to be removed from TabStripCollection.
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 7071948e..48932e1c 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -6,6 +6,7 @@ #include <algorithm> #include <memory> +#include <optional> #include <set> #include <string> #include <unordered_map> @@ -44,6 +45,7 @@ #include "chrome/browser/ui/tabs/organization/tab_organization_service.h" #include "chrome/browser/ui/tabs/organization/tab_organization_service_factory.h" #include "chrome/browser/ui/tabs/organization/tab_organization_session.h" +#include "chrome/browser/ui/tabs/pinned_tab_collection.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h" #include "chrome/browser/ui/tabs/tab_collection.h" @@ -55,6 +57,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/tabs/tab_utils.h" +#include "chrome/browser/ui/tabs/unpinned_tab_collection.h" #include "chrome/browser/ui/thumbnails/thumbnail_tab_helper.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/user_notes/user_notes_controller.h" @@ -328,6 +331,12 @@ return kNoTab; } + if (!IsContentsDataVector()) { + std::optional<size_t> index_of_tab = + GetContentsDataAsCollection()->GetIndexOfTabRecursive(tab_model); + return index_of_tab.value_or(kNoTab); + } + const auto is_same_tab = [tab_model](const std::unique_ptr<tabs::TabModel>& other) { return other.get() == tab_model; @@ -525,7 +534,8 @@ std::optional<int> next_selected_index = DetermineNewSelectedIndex(index_at_time_of_removal); - UngroupTab(index_at_time_of_removal); + UngroupTab(index_at_time_of_removal, + GetTabGroupForTab(index_before_any_removals)); std::unique_ptr<tabs::TabModel> old_data; if (IsContentsDataVector()) { @@ -651,11 +661,14 @@ to_position = ConstrainMoveIndex(to_position, IsTabPinned(index)); - if (index == to_position) + if (index == to_position) { return to_position; + } MoveWebContentsAtImpl(index, to_position, select_after_move); - EnsureGroupContiguity(to_position); + if (IsContentsDataVector()) { + EnsureGroupContiguity(to_position); + } return to_position; } @@ -1229,16 +1242,18 @@ std::optional<tab_groups::TabGroupVisualData> group_data) { ReentrancyCheck reentrancy_check(&reentrancy_guard_); - if (!group_model_) + if (!group_model_) { return; + } if (group_id.has_value()) { const bool group_exists = group_model_->ContainsTabGroup(group_id.value()); - if (!group_exists) + if (!group_exists) { group_model_->AddTabGroup(group_id.value(), group_data); - GroupTab(index, group_id.value()); + } + GroupTab(index, group_id.value(), GetTabGroupForTab(index)); } else { - UngroupTab(index); + UngroupTab(index, GetTabGroupForTab(index)); } } @@ -1909,7 +1924,10 @@ void TabStripModel::WriteIntoTrace(perfetto::TracedValue context) const { auto dict = std::move(context).WriteDictionary(); dict.Add("active_index", active_index()); - dict.Add("tabs", GetContentsDataAsVector()); + // TODO(b/335438706): Add tracing for collection infrastructure. + if (IsContentsDataVector()) { + dict.Add("tabs", GetContentsDataAsVector()); + } } /////////////////////////////////////////////////////////////////////////////// @@ -2057,7 +2075,7 @@ // Unset the group at the index of the inserted WebContents so that the // GroupTab functionality isn't skipped. GetTabAtIndex(index)->set_group(std::nullopt); - GroupTab(index, group.value()); + GroupTab(index, group.value(), GetTabGroupForTab(index)); } return index; @@ -2256,7 +2274,7 @@ TabStripUserGestureDetails detail) { // This may happen during automated testing or if a user somehow buffers // many key accelerators. - if (GetContentsDataAsVector().empty()) { + if (empty()) { return; } @@ -2302,7 +2320,7 @@ // actually moving the tab just change its group membership. if (group_model_ && current_group != target_group) { if (current_group.has_value()) { - UngroupTab(current_index); + UngroupTab(current_index, GetTabGroupForTab(current_index)); return; } else if (target_group.has_value()) { // If the tab is at a group boundary and the group is collapsed, treat the @@ -2315,7 +2333,8 @@ ? tabs_in_group.end() - 1 : tabs_in_group.start(); } else { - GroupTab(current_index, target_group.value()); + GroupTab(current_index, target_group.value(), + GetTabGroupForTab(current_index)); return; } } @@ -2331,14 +2350,55 @@ TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); - CHECK_LT(index, static_cast<int>(GetContentsDataAsVector().size())); - CHECK_LT(to_position, static_cast<int>(GetContentsDataAsVector().size())); + CHECK_LT(index, count()); + CHECK_LT(to_position, count()); + + if (IsContentsDataVector()) { + MoveWebContentsAtImplWithVector(index, to_position, select_after_move); + } else { + MoveWebContentsAtImplWithCollection(index, to_position, select_after_move); + } +} + +void TabStripModel::MoveWebContentsAtImplWithVector(int index, + int to_position, + bool select_after_move) { + CHECK(IsContentsDataVector()); std::unique_ptr<tabs::TabModel> moved_data = std::move(GetContentsDataAsVector()[index]); - WebContents* web_contents = moved_data->contents(); + WebContents* const web_contents = moved_data->contents(); + GetContentsDataAsVector().erase(GetContentsDataAsVector().begin() + index); GetContentsDataAsVector().insert( GetContentsDataAsVector().begin() + to_position, std::move(moved_data)); + SendMoveNotificationForWebContents(index, to_position, select_after_move, + web_contents); +} + +void TabStripModel::MoveWebContentsAtImplWithCollection( + int index, + int to_position, + bool select_after_move) { + CHECK(!IsContentsDataVector()); + const bool is_tab_pinned = IsTabPinned(to_position); + + std::unique_ptr<tabs::TabModel> moved_data = + GetContentsDataAsCollection()->RemoveTabAtIndexRecursive(index); + WebContents* const web_contents = moved_data->contents(); + + GetContentsDataAsCollection()->AddTabRecursive( + std::move(moved_data), to_position, std::nullopt, is_tab_pinned); + + SendMoveNotificationForWebContents(index, to_position, select_after_move, + web_contents); +} + +void TabStripModel::SendMoveNotificationForWebContents( + int index, + int to_position, + bool select_after_move, + WebContents* web_contents) { + TabStripSelectionChange selection(GetActiveWebContents(), selection_model_); selection_model_.Move(index, to_position, 1); if (!selection_model_.IsSelected(to_position) && select_after_move) { @@ -2472,7 +2532,7 @@ std::vector<int> tabs_right_of_group; for (int index : indices) { if (index >= first_tab_in_group && index <= last_tab_in_group) { - GroupTab(index, group); + GroupTab(index, group, GetTabGroupForTab(index)); } else if (index < first_tab_in_group) { tabs_left_of_group.push_back(index); } else { @@ -2526,9 +2586,12 @@ int index, int new_index, std::optional<tab_groups::TabGroupId> new_group) { - if (!group_model_) + if (!group_model_) { return; + } + const std::optional<tab_groups::TabGroupId> old_group = + GetTabGroupForTab(index); if (new_group.has_value()) { // Unpin tabs when grouping -- the states should be mutually exclusive. // Here we move the tab twice to ensure the tabstrip is always in a valid @@ -2537,29 +2600,18 @@ index = SetTabPinnedImpl(index, false); } - std::optional<tab_groups::TabGroupId> old_group = GetTabGroupForTab(index); - if (old_group.has_value()) { - // TODO (1302144): We don't maintain group contiguity in this case. If - // |index| is in the middle of |old_group|, GroupTab will notify observers - // while |old_group| is split in twain. Simply reordering the move and - // group actions won't do it; we'd need to move, ungroup, move, and then - // group. - GroupTab(index, new_group.value()); - if (index != new_index) - MoveWebContentsAtImpl(index, new_index, false); - } else { - // Move the tab now so that group contiguity is preserved. - // When grouping, this will move the tab next to |new_group|. - if (index != new_index) - MoveWebContentsAtImpl(index, new_index, false); - GroupTab(new_index, new_group.value()); + if (index != new_index) { + MoveWebContentsAtImpl(index, new_index, false); } + GroupTab(new_index, new_group.value(), old_group); + } else { // Move the tab now so that group contiguity is preserved. // When ungrouping, this will move the tab to the edge of |old_group|. - if (index != new_index) + if (index != new_index) { MoveWebContentsAtImpl(index, new_index, false); - UngroupTab(new_index); + } + UngroupTab(new_index, old_group); } } @@ -2568,13 +2620,16 @@ delegate_->AddToReadLater(GetWebContentsAt(index)); } -std::optional<tab_groups::TabGroupId> TabStripModel::UngroupTab(int index) { - if (!group_model_) +std::optional<tab_groups::TabGroupId> TabStripModel::UngroupTab( + int index, + const std::optional<tab_groups::TabGroupId> old_group) { + if (!group_model_) { return std::nullopt; + } - std::optional<tab_groups::TabGroupId> group = GetTabGroupForTab(index); - if (!group.has_value()) + if (!old_group.has_value()) { return std::nullopt; + } // Update the tab. GetTabAtIndex(index)->set_group(std::nullopt); @@ -2584,26 +2639,30 @@ } // Update the group model. - TabGroup* tab_group = group_model_->GetTabGroup(group.value()); + TabGroup* tab_group = group_model_->GetTabGroup(old_group.value()); tab_group->RemoveTab(); - if (tab_group->IsEmpty()) - group_model_->RemoveTabGroup(group.value()); + if (tab_group->IsEmpty()) { + group_model_->RemoveTabGroup(old_group.value()); + } - return group; + return old_group; } -void TabStripModel::GroupTab(int index, const tab_groups::TabGroupId& group) { +void TabStripModel::GroupTab( + int index, + const tab_groups::TabGroupId& group, + const std::optional<tab_groups::TabGroupId> old_group) { if (!group_model_) return; // Check for an old group first, so that any groups that are changed can be // notified appropriately. - std::optional<tab_groups::TabGroupId> old_group = GetTabGroupForTab(index); if (old_group.has_value()) { - if (old_group.value() == group) + if (old_group.value() == group) { return; - else - UngroupTab(index); + } else { + UngroupTab(index, old_group); + } } GetTabAtIndex(index)->set_group(group); for (auto& observer : observers_) { @@ -2650,26 +2709,59 @@ } // Upgroup tabs if pinning -- the states should be mutually exclusive. - if (pinned && group_model_) - UngroupTab(index); + if (pinned && group_model_) { + UngroupTab(index, GetTabGroupForTab(index)); + } // The tab's position may have to change as the pinned tab state is changing. - int non_pinned_tab_index = IndexOfFirstNonPinnedTab(); - tab_model->set_pinned(pinned); - if (pinned && index != non_pinned_tab_index) { - MoveWebContentsAtImpl(index, non_pinned_tab_index, false); - index = non_pinned_tab_index; - } else if (!pinned && index + 1 != non_pinned_tab_index) { - MoveWebContentsAtImpl(index, non_pinned_tab_index - 1, false); - index = non_pinned_tab_index - 1; - } - - CHECK_EQ(GetTabAtIndex(index), tab_model); + const int index_after_pin_state_update = + UpdatePinAndMoveWebContents(index, pinned); + CHECK_EQ(GetTabAtIndex(index_after_pin_state_update), tab_model); for (auto& observer : observers_) { - observer.TabPinnedStateChanged(this, tab_model->contents(), index); + observer.TabPinnedStateChanged(this, tab_model->contents(), + index_after_pin_state_update); } - return index; + return index_after_pin_state_update; +} + +int TabStripModel::UpdatePinAndMoveWebContents(int index, bool pinned) { + tabs::TabModel* const tab_model = GetTabAtIndex(index); + const int non_pinned_tab_index = IndexOfFirstNonPinnedTab(); + + if (IsContentsDataVector()) { + tab_model->set_pinned(pinned); + if (pinned && index != non_pinned_tab_index) { + MoveWebContentsAtImpl(index, non_pinned_tab_index, false); + return non_pinned_tab_index; + } else if (!pinned && index + 1 != non_pinned_tab_index) { + MoveWebContentsAtImpl(index, non_pinned_tab_index - 1, false); + return non_pinned_tab_index - 1; + } + return index; + } else { + if (pinned) { + std::unique_ptr<tabs::TabModel> tab_to_pin = + GetContentsDataAsCollection()->RemoveTabAtIndexRecursive(index); + GetContentsDataAsCollection()->GetPinnedCollection()->AppendTab( + std::move(tab_to_pin)); + } else { + std::unique_ptr<tabs::TabModel> tab_to_unpin = + GetContentsDataAsCollection()->RemoveTabAtIndexRecursive(index); + GetContentsDataAsCollection()->GetUnpinnedCollection()->AddTab( + std::move(tab_to_unpin), 0); + } + + const int index_after_updating_pinned_state = + pinned ? non_pinned_tab_index : non_pinned_tab_index - 1; + + if (index_after_updating_pinned_state != index) { + SendMoveNotificationForWebContents(index, + index_after_updating_pinned_state, + false, tab_model->contents()); + } + return index_after_updating_pinned_state; + } } std::vector<int> TabStripModel::SetTabsPinned(const std::vector<int>& indices, @@ -2784,12 +2876,12 @@ if (old_group != new_left_group && old_group != new_right_group) { if (new_left_group == new_right_group && new_left_group.has_value()) { // The tab is in the middle of an existing group, so add it to that group. - GroupTab(index, new_left_group.value()); + GroupTab(index, new_left_group.value(), GetTabGroupForTab(index)); } else if (old_group.has_value() && group_model_->GetTabGroup(old_group.value())->tab_count() > 1) { // The tab is between groups and its group is non-contiguous, so clear // this tab's group. - UngroupTab(index); + UngroupTab(index, GetTabGroupForTab(index)); } } }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 79a335dd..1ab2cdb8 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -776,6 +776,23 @@ int to_position, bool select_after_move); + // Implementation of moving a webcontent when the `contents_data` is a tab + // collection. + void MoveWebContentsAtImplWithCollection(int index, + int to_position, + bool select_after_move); + + // Implementation of moving a webcontent when the `contents_data` is a vector. + void MoveWebContentsAtImplWithVector(int index, + int to_position, + bool select_after_move); + + // Sends a move notification to the tabstrip model observers for a webcontent. + void SendMoveNotificationForWebContents(int index, + int to_position, + bool select_after_move, + content::WebContents* web_contents); + // Implementation of MoveSelectedTabsTo. Moves |length| of the selected tabs // starting at |start| to |index|. See MoveSelectedTabsTo for more details. void MoveSelectedTabsToImpl(int index, size_t start, size_t length); @@ -809,12 +826,16 @@ // Helper function for MoveAndSetGroup. Removes the tab at |index| from the // group that contains it, if any. Also deletes that group, if it now contains // no tabs. Returns that group. - std::optional<tab_groups::TabGroupId> UngroupTab(int index); + std::optional<tab_groups::TabGroupId> UngroupTab( + int index, + const std::optional<tab_groups::TabGroupId> old_group); // Helper function for MoveAndSetGroup. Adds the tab at |index| to |group|, // updates the group model, and notifies the observers if the group at that // index would change. - void GroupTab(int index, const tab_groups::TabGroupId& group); + void GroupTab(int index, + const tab_groups::TabGroupId& group, + const std::optional<tab_groups::TabGroupId> old_group); // Disconnects any saved tab groups whose tabs are a subset of `indices`. void DisconnectSavedTabGroups(const std::vector<int>& indices) const; @@ -823,6 +844,10 @@ // necessary. Returns the new index of the tab. int SetTabPinnedImpl(int index, bool pinned); + // Updates the pinned state of the tab model and moves the tab within + // `contents_data`. This is a helper method called by `SetTabPinnedImpl()`. + int UpdatePinAndMoveWebContents(int index, bool pinned); + // Changes the pinned state of all tabs at `indices`, moving them in the // process if necessary. Returns the new locations of all of those tabs. std::vector<int> SetTabsPinned(const std::vector<int>& indices, bool pinned);
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index ec919d47..bc490ed 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -33,6 +33,7 @@ #include "chrome/browser/ui/tabs/tab_strip_user_gesture_details.h" #include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -375,9 +376,17 @@ } // namespace -class TabStripModelTest : public testing::Test { +class TabStripModelTest : public testing::Test, + public ::testing::WithParamInterface<bool> { public: - TabStripModelTest() : profile_(new TestingProfile) {} + TabStripModelTest() : profile_(new TestingProfile) { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/GetParam() + ? std::vector< + base::test::FeatureRef>{features::kTabStripCollectionStorage} + : std::vector<base::test::FeatureRef>{}, + /*disabled_features=*/std::vector<base::test::FeatureRef>{}); + } TabStripModelTest(const TabStripModelTest&) = delete; TabStripModelTest& operator=(const TabStripModelTest&) = delete; @@ -465,10 +474,11 @@ private: content::BrowserTaskEnvironment task_environment_; content::RenderViewHostTestEnabler rvh_test_enabler_; + base::test::ScopedFeatureList scoped_feature_list_; const std::unique_ptr<TestingProfile> profile_; }; -TEST_F(TabStripModelTest, TestBasicAPI) { +TEST_P(TabStripModelTest, TestBasicAPI) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); MockTabStripModelObserver observer; @@ -696,7 +706,7 @@ tabstrip.RemoveObserver(&observer); } -TEST_F(TabStripModelTest, TestTabHandlesStaticTabstrip) { +TEST_P(TabStripModelTest, TestTabHandlesStaticTabstrip) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -712,7 +722,7 @@ EXPECT_EQ(handle2, tabstrip.GetTabHandleAt(1)); } -TEST_F(TabStripModelTest, TestTabHandlesMovingTabInSameTabstrip) { +TEST_P(TabStripModelTest, TestTabHandlesMovingTabInSameTabstrip) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -730,7 +740,7 @@ EXPECT_EQ(handle1, tabstrip.GetTabHandleAt(1)); } -TEST_F(TabStripModelTest, TestTabHandlesTabClosed) { +TEST_P(TabStripModelTest, TestTabHandlesTabClosed) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -745,7 +755,7 @@ EXPECT_EQ(nullptr, handle.Get()); } -TEST_F(TabStripModelTest, TestTabHandlesOutOfBounds) { +TEST_P(TabStripModelTest, TestTabHandlesOutOfBounds) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -759,7 +769,7 @@ EXPECT_DEATH_IF_SUPPORTED(tabstrip.GetTabHandleAt(-1).Get(), ""); } -TEST_F(TabStripModelTest, TestTabHandlesAcrossModels) { +TEST_P(TabStripModelTest, TestTabHandlesAcrossModels) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -807,7 +817,7 @@ EXPECT_EQ(false, handle.Get()->blocked()); } -TEST_F(TabStripModelTest, TestBasicOpenerAPI) { +TEST_P(TabStripModelTest, TestBasicOpenerAPI) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -915,7 +925,7 @@ } // Tests opening background tabs. -TEST_F(TabStripModelTest, TestLTRInsertionOptions) { +TEST_P(TabStripModelTest, TestLTRInsertionOptions) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -947,7 +957,7 @@ // that this tab is opened adjacent to the opener, then closes it. // Finally it tests that a tab opened for some non-link purpose opens at the // end of the strip, not bundled to any existing context. -TEST_F(TabStripModelTest, TestInsertionIndexDetermination) { +TEST_P(TabStripModelTest, TestInsertionIndexDetermination) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1029,7 +1039,7 @@ // Tests that non-adjacent tabs with an opener are ignored when deciding where // to position tabs. -TEST_F(TabStripModelTest, TestInsertionIndexDeterminationAfterDragged) { +TEST_P(TabStripModelTest, TestInsertionIndexDeterminationAfterDragged) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1083,7 +1093,7 @@ // Tests that grandchild tabs are considered to be opened by their grandparent // tab when deciding where to position tabs. -TEST_F(TabStripModelTest, TestInsertionIndexDeterminationNestedOpener) { +TEST_P(TabStripModelTest, TestInsertionIndexDeterminationNestedOpener) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1159,7 +1169,7 @@ // Tests that selection is shifted to the correct tab when a tab is closed. // If the tab is in the background when it is closed, the selection does not // change. -TEST_F(TabStripModelTest, CloseInactiveTabKeepsSelection) { +TEST_P(TabStripModelTest, CloseInactiveTabKeepsSelection) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1183,7 +1193,7 @@ // Tests that selection is shifted to the correct tab when a tab is closed. // If the tab doesn't have an opener or a group, selection shifts to the right. -TEST_F(TabStripModelTest, CloseActiveTabShiftsSelectionRight) { +TEST_P(TabStripModelTest, CloseActiveTabShiftsSelectionRight) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1214,7 +1224,11 @@ // Tests that selection is shifted to the correct tab when a tab is closed. // If the tab doesn't have an opener but is in a group, selection shifts to // another tab in the same group. -TEST_F(TabStripModelTest, CloseGroupedTabShiftsSelectionWithinGroup) { +TEST_P(TabStripModelTest, CloseGroupedTabShiftsSelectionWithinGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1246,7 +1260,11 @@ // Tests that the active selection will change to another non collapsed tab when // the active index is in the collapsing group. -TEST_F(TabStripModelTest, CollapseGroupShiftsSelection_SuccessNextTab) { +TEST_P(TabStripModelTest, CollapseGroupShiftsSelection_SuccessNextTab) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1276,7 +1294,11 @@ // Tests that the active selection will change to another non collapsed tab when // the active index is in the collapsing group. -TEST_F(TabStripModelTest, CollapseGroupShiftsSelection_SuccessPreviousTab) { +TEST_P(TabStripModelTest, CollapseGroupShiftsSelection_SuccessPreviousTab) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1306,7 +1328,11 @@ // Tests that there is no valid selection to shift to when the active tab is in // the group that will be collapsed. -TEST_F(TabStripModelTest, CollapseGroupShiftsSelection_NoAvailableTabs) { +TEST_P(TabStripModelTest, CollapseGroupShiftsSelection_NoAvailableTabs) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1337,7 +1363,7 @@ // Tests that selection is shifted to the correct tab when a tab is closed. // If the tab does have an opener, selection shifts to the next tab opened by // the same opener scanning LTR. -TEST_F(TabStripModelTest, CloseTabWithOpenerShiftsSelectionWithinOpened) { +TEST_P(TabStripModelTest, CloseTabWithOpenerShiftsSelectionWithinOpened) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1367,7 +1393,7 @@ // Tests that selection is shifted to the correct tab when a tab is closed. // If the tab has an opener but no "siblings" opened by the same opener, // selection shifts to the opener itself. -TEST_F(TabStripModelTest, CloseTabWithOpenerShiftsSelectionToOpener) { +TEST_P(TabStripModelTest, CloseTabWithOpenerShiftsSelectionToOpener) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -1393,7 +1419,7 @@ // Tests IsContextMenuCommandEnabled and ExecuteContextMenuCommand with // CommandCloseTab. -TEST_F(TabStripModelTest, CommandCloseTab) { +TEST_P(TabStripModelTest, CommandCloseTab) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1444,7 +1470,7 @@ // Tests IsContextMenuCommandEnabled and ExecuteContextMenuCommand with // CommandCloseOtherTabs. -TEST_F(TabStripModelTest, CommandCloseOtherTabs) { +TEST_P(TabStripModelTest, CommandCloseOtherTabs) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1506,7 +1532,7 @@ // Tests IsContextMenuCommandEnabled and ExecuteContextMenuCommand with // CommandCloseTabsToRight. -TEST_F(TabStripModelTest, CommandCloseTabsToRight) { +TEST_P(TabStripModelTest, CommandCloseTabsToRight) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1529,7 +1555,7 @@ // Tests IsContextMenuCommandEnabled and ExecuteContextMenuCommand with // CommandTogglePinned. -TEST_F(TabStripModelTest, CommandTogglePinned) { +TEST_P(TabStripModelTest, CommandTogglePinned) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1560,7 +1586,11 @@ // Tests IsContextMenuCommandEnabled and ExecuteContextMenuCommand with // CommandToggleGrouped. -TEST_F(TabStripModelTest, CommandToggleGrouped) { +TEST_P(TabStripModelTest, CommandToggleGrouped) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1610,7 +1640,7 @@ // - Close Tab // - Close Other Tabs // - Close Tabs To Right -TEST_F(TabStripModelTest, TestContextMenuCloseCommands) { +TEST_P(TabStripModelTest, TestContextMenuCloseCommands) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1660,7 +1690,7 @@ EXPECT_TRUE(tabstrip.empty()); } -TEST_F(TabStripModelTest, GetIndicesClosedByCommand) { +TEST_P(TabStripModelTest, GetIndicesClosedByCommand) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1713,7 +1743,7 @@ // Tests whether or not WebContentses are inserted in the correct position // using this "smart" function with a simulated middle click action on a series // of links on the home page. -TEST_F(TabStripModelTest, AddWebContents_MiddleClickLinksAndClose) { +TEST_P(TabStripModelTest, AddWebContents_MiddleClickLinksAndClose) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1787,7 +1817,7 @@ // Tests whether or not a WebContents created by a left click on a link // that opens a new tab is inserted correctly adjacent to the tab that spawned // it. -TEST_F(TabStripModelTest, AddWebContents_LeftClickPopup) { +TEST_P(TabStripModelTest, AddWebContents_LeftClickPopup) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1841,7 +1871,7 @@ // Tests whether or not new tabs that should split context (typed pages, // generated urls, also blank tabs) open at the end of the tabstrip instead of // in the middle. -TEST_F(TabStripModelTest, AddWebContents_CreateNewBlankTab) { +TEST_P(TabStripModelTest, AddWebContents_CreateNewBlankTab) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1902,7 +1932,7 @@ // Tests whether opener state is correctly forgotten when the user switches // context. -TEST_F(TabStripModelTest, AddWebContents_ForgetOpeners) { +TEST_P(TabStripModelTest, AddWebContents_ForgetOpeners) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -1973,7 +2003,11 @@ // Tests whether or not a WebContents in a new tab belongs in the same tab // group as its opener. -TEST_F(TabStripModelTest, AddWebContents_LinkOpensInSameGroupAsOpener) { +TEST_P(TabStripModelTest, AddWebContents_LinkOpensInSameGroupAsOpener) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); MockTabStripModelObserver observer; @@ -2006,7 +2040,11 @@ // Tests that a inserting a new ungrouped tab between two tabs in the same group // will add that new tab to the group. -TEST_F(TabStripModelTest, AddWebContents_UngroupedTabDoesNotBreakContinuity) { +TEST_P(TabStripModelTest, AddWebContents_UngroupedTabDoesNotBreakContinuity) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); ASSERT_TRUE(tabstrip.empty()); @@ -2040,7 +2078,7 @@ ASSERT_TRUE(tabstrip.empty()); } // Added for http://b/issue?id=958960 -TEST_F(TabStripModelTest, AppendContentsReselectionTest) { +TEST_P(TabStripModelTest, AppendContentsReselectionTest) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -2071,7 +2109,7 @@ } // Added for http://b/issue?id=1027661 -TEST_F(TabStripModelTest, ReselectionConsidersChildrenTest) { +TEST_P(TabStripModelTest, ReselectionConsidersChildrenTest) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -2127,7 +2165,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, NewTabAtEndOfStripInheritsOpener) { +TEST_P(TabStripModelTest, NewTabAtEndOfStripInheritsOpener) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -2202,7 +2240,7 @@ // A test of navigations in a tab that is part of a tree of openers from some // parent tab. If the navigations are link clicks, the opener relationships of // the tab. If they are of any other type, they are not preserved. -TEST_F(TabStripModelTest, NavigationForgetsOpeners) { +TEST_P(TabStripModelTest, NavigationForgetsOpeners) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -2253,7 +2291,7 @@ // A test for the "quick look" use case where the user can open a new tab at the // end of the tab strip, do one search, and then close the tab to get back to // where they were. -TEST_F(TabStripModelTest, NavigationForgettingDoesntAffectNewTab) { +TEST_P(TabStripModelTest, NavigationForgettingDoesntAffectNewTab) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -2371,7 +2409,7 @@ } // namespace // Tests that fast shutdown is attempted appropriately. -TEST_F(TabStripModelTest, FastShutdown) { +TEST_P(TabStripModelTest, FastShutdown) { UnloadListenerTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); MockTabStripModelObserver observer; @@ -2436,7 +2474,7 @@ } // Tests various permutations of pinning tabs. -TEST_F(TabStripModelTest, Pinning) { +TEST_P(TabStripModelTest, Pinning) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); MockTabStripModelObserver observer; @@ -2599,7 +2637,7 @@ // Makes sure the TabStripModel calls the right observer methods during a // replace. -TEST_F(TabStripModelTest, ReplaceSendsSelected) { +TEST_P(TabStripModelTest, ReplaceSendsSelected) { typedef MockTabStripModelObserver::State State; TestTabStripModelDelegate delegate; @@ -2655,7 +2693,7 @@ // Ensure pinned tabs are not mixed with non-pinned tabs when using // MoveWebContentsAt. -TEST_F(TabStripModelTest, MoveWebContentsAtWithPinned) { +TEST_P(TabStripModelTest, MoveWebContentsAtWithPinned) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 6, 3, "0")); @@ -2682,7 +2720,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabNext) { +TEST_P(TabStripModelTest, MoveTabNext) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 6, 3, "3")); @@ -2700,7 +2738,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabNext_Pinned) { +TEST_P(TabStripModelTest, MoveTabNext_Pinned) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 6, 3, "0")); @@ -2718,7 +2756,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabNext_Group) { +TEST_P(TabStripModelTest, MoveTabNext_Group) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 4, 0, "0")); @@ -2746,7 +2788,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabNext_GroupAtEnd) { +TEST_P(TabStripModelTest, MoveTabNext_GroupAtEnd) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 2, 0, "0")); @@ -2765,7 +2811,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabNext_PinnedDoesNotGroup) { +TEST_P(TabStripModelTest, MoveTabNext_PinnedDoesNotGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 4, 1, "0")); @@ -2781,7 +2831,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabPrevious) { +TEST_P(TabStripModelTest, MoveTabPrevious) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 6, 3, "5")); @@ -2799,7 +2849,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabPrevious_Pinned) { +TEST_P(TabStripModelTest, MoveTabPrevious_Pinned) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 6, 3, "2")); @@ -2817,7 +2867,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabPrevious_Group) { +TEST_P(TabStripModelTest, MoveTabPrevious_Group) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 4, 0, "3")); @@ -2845,7 +2899,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveTabPrevious_GroupAtEnd) { +TEST_P(TabStripModelTest, MoveTabPrevious_GroupAtEnd) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_NO_FATAL_FAILURE(PrepareTabstripForSelectionTest(&strip, 2, 0, "1")); @@ -2864,7 +2922,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveSelectedTabsTo) { +TEST_P(TabStripModelTest, MoveSelectedTabsTo) { struct TestData { // Number of tabs the tab strip should have. const int tab_count; @@ -2928,7 +2986,7 @@ } // Tests that moving a tab forgets all openers referencing it. -TEST_F(TabStripModelTest, MoveSelectedTabsTo_ForgetOpeners) { +TEST_P(TabStripModelTest, MoveSelectedTabsTo_ForgetOpeners) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -2993,7 +3051,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, CloseSelectedTabs) { +TEST_P(TabStripModelTest, CloseSelectedTabs) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); for (int i = 0; i < 3; ++i) @@ -3005,7 +3063,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, FirstTabIsActive) { +TEST_P(TabStripModelTest, FirstTabIsActive) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -3016,7 +3074,7 @@ EXPECT_EQ(0, strip.active_index()); } -TEST_F(TabStripModelTest, MultipleSelection) { +TEST_P(TabStripModelTest, MultipleSelection) { typedef MockTabStripModelObserver::State State; TestTabStripModelDelegate delegate; @@ -3119,7 +3177,7 @@ // Verifies that if we change the selection from a multi selection to a single // selection, but not in a way that changes the selected_index that // TabSelectionChanged is invoked. -TEST_F(TabStripModelTest, MultipleToSingle) { +TEST_P(TabStripModelTest, MultipleToSingle) { typedef MockTabStripModelObserver::State State; TestTabStripModelDelegate delegate; @@ -3230,7 +3288,7 @@ // Verifies a newly inserted tab retains its previous blocked state. // http://crbug.com/276334 -TEST_F(TabStripModelTest, TabBlockedState) { +TEST_P(TabStripModelTest, TabBlockedState) { // Start with a source tab strip. TestTabStripModelDelegate dummy_tab_strip_delegate; TabStripModel strip_src(&dummy_tab_strip_delegate, profile()); @@ -3284,7 +3342,7 @@ // Verifies ordering of tabs opened via a link from a pinned tab with a // subsequent pinned tab. -TEST_F(TabStripModelTest, LinkClicksWithPinnedTabOrdering) { +TEST_P(TabStripModelTest, LinkClicksWithPinnedTabOrdering) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -3319,7 +3377,7 @@ // This test covers a bug in TabStripModel::MoveWebContentsAt(). Specifically // if |select_after_move| was true it checked if the index // select_after_move (as an int) was selected rather than |to_position|. -TEST_F(TabStripModelTest, MoveWebContentsAt) { +TEST_P(TabStripModelTest, MoveWebContentsAt) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -3340,7 +3398,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, NewTabsUngrouped) { +TEST_P(TabStripModelTest, NewTabsUngrouped) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), false); @@ -3352,7 +3410,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroup) { +TEST_P(TabStripModelTest, AddTabToNewGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_TRUE(strip.SupportsTabGroups()); @@ -3368,7 +3430,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupUpdatesObservers) { +TEST_P(TabStripModelTest, AddTabToNewGroupUpdatesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); ASSERT_TRUE(strip.SupportsTabGroups()); @@ -3385,7 +3451,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ReplacingTabGroupUpdatesObservers) { +TEST_P(TabStripModelTest, ReplacingTabGroupUpdatesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); ASSERT_TRUE(tab_strip.SupportsTabGroups()); @@ -3405,7 +3475,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroup) { +TEST_P(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); ASSERT_TRUE(tab_strip.SupportsTabGroups()); @@ -3426,7 +3500,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroupTwoGroups) { +TEST_P(TabStripModelTest, AddTabToNewGroupMiddleOfExistingGroupTwoGroups) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); PrepareTabs(&tab_strip, 4); @@ -3440,7 +3518,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupReorders) { +TEST_P(TabStripModelTest, AddTabToNewGroupReorders) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); PrepareTabs(&tab_strip, 3); @@ -3455,7 +3537,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupUnpins) { +TEST_P(TabStripModelTest, AddTabToNewGroupUnpins) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); PrepareTabs(&tab_strip, 2); @@ -3468,7 +3554,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupUnpinsAndReorders) { +TEST_P(TabStripModelTest, AddTabToNewGroupUnpinsAndReorders) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel tab_strip(&delegate, profile()); PrepareTabs(&tab_strip, 3); @@ -3482,7 +3572,11 @@ tab_strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToNewGroupMovesPinnedAndUnpinnedTabs) { +TEST_P(TabStripModelTest, AddTabToNewGroupMovesPinnedAndUnpinnedTabs) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -3499,7 +3593,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToExistingGroupIdempotent) { +TEST_P(TabStripModelTest, AddTabToExistingGroupIdempotent) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -3517,7 +3615,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToExistingGroup) { +TEST_P(TabStripModelTest, AddTabToExistingGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -3533,7 +3635,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToExistingGroupUpdatesObservers) { +TEST_P(TabStripModelTest, AddTabToExistingGroupUpdatesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -3550,7 +3656,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToLeftOfExistingGroupReorders) { +TEST_P(TabStripModelTest, AddTabToLeftOfExistingGroupReorders) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3566,7 +3676,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToRighOfExistingGroupReorders) { +TEST_P(TabStripModelTest, AddTabToRighOfExistingGroupReorders) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3583,7 +3697,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToExistingGroupReorders) { +TEST_P(TabStripModelTest, AddTabToExistingGroupReorders) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -3601,7 +3719,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddTabToExistingGroupUnpins) { +TEST_P(TabStripModelTest, AddTabToExistingGroupUnpins) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -3618,7 +3740,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, PinTabInGroupUngroups) { +TEST_P(TabStripModelTest, PinTabInGroupUngroups) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -3633,7 +3759,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupNoopForUngroupedTab) { +TEST_P(TabStripModelTest, RemoveTabFromGroupNoopForUngroupedTab) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -3647,7 +3773,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroup) { +TEST_P(TabStripModelTest, RemoveTabFromGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3660,7 +3790,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupUpdatesObservers) { +TEST_P(TabStripModelTest, RemoveTabFromGroupUpdatesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -3679,7 +3813,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupMaintainsOrder) { +TEST_P(TabStripModelTest, RemoveTabFromGroupMaintainsOrder) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -3694,7 +3832,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupDoesntReorderIfNoGroup) { +TEST_P(TabStripModelTest, RemoveTabFromGroupDoesntReorderIfNoGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3706,8 +3848,12 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, +TEST_P(TabStripModelTest, RemoveTabFromGroupMaintainsRelativeOrderOfSelectedTabs) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -3724,7 +3870,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupMixtureOfGroups) { +TEST_P(TabStripModelTest, RemoveTabFromGroupMixtureOfGroups) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -3743,7 +3893,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, RemoveTabFromGroupDeletesGroup) { +TEST_P(TabStripModelTest, RemoveTabFromGroupDeletesGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3757,7 +3911,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddToNewGroupDeletesGroup) { +TEST_P(TabStripModelTest, AddToNewGroupDeletesGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3773,7 +3931,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AddToExistingGroupDeletesGroup) { +TEST_P(TabStripModelTest, AddToExistingGroupDeletesGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3791,7 +3953,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, CloseTabDeletesGroup) { +TEST_P(TabStripModelTest, CloseTabDeletesGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3803,7 +3969,11 @@ EXPECT_EQ(strip.group_model()->ListTabGroups().size(), 0U); } -TEST_F(TabStripModelTest, CloseTabNotifiesObserversOfGroupChange) { +TEST_P(TabStripModelTest, CloseTabNotifiesObserversOfGroupChange) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; MockTabStripModelObserver observer; TabStripModel strip(&delegate, profile()); @@ -3819,7 +3989,11 @@ EXPECT_EQ(0u, observer.group_updates().size()); } -TEST_F(TabStripModelTest, InsertWebContentsAtWithGroupNotifiesObservers) { +TEST_P(TabStripModelTest, InsertWebContentsAtWithGroupNotifiesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; MockTabStripModelObserver observer; TabStripModel strip(&delegate, profile()); @@ -3844,7 +4018,11 @@ // When inserting a WebContents, if a group is not specified, the new tab // should be left ungrouped. -TEST_F(TabStripModelTest, InsertWebContentsAtDoesNotGroupByDefault) { +TEST_P(TabStripModelTest, InsertWebContentsAtDoesNotGroupByDefault) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3863,7 +4041,11 @@ // When inserting a WebContents, if a group is specified, the new tab should be // added to that group. -TEST_F(TabStripModelTest, InsertWebContentsAtWithGroupGroups) { +TEST_P(TabStripModelTest, InsertWebContentsAtWithGroupGroups) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContentsWithID(0), true); @@ -3882,7 +4064,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, NewTabWithGroup) { +TEST_P(TabStripModelTest, NewTabWithGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3896,7 +4082,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, NewTabWithGroupDeletedCorrectly) { +TEST_P(TabStripModelTest, NewTabWithGroupDeletedCorrectly) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); strip.AppendWebContents(CreateWebContents(), true); @@ -3912,7 +4102,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, NewTabWithoutIndexInsertsAtEndOfGroup) { +TEST_P(TabStripModelTest, NewTabWithoutIndexInsertsAtEndOfGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3925,7 +4119,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, DiscontinuousNewTabIndexTooHigh) { +TEST_P(TabStripModelTest, DiscontinuousNewTabIndexTooHigh) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3938,7 +4136,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, DiscontinuousNewTabIndexTooLow) { +TEST_P(TabStripModelTest, DiscontinuousNewTabIndexTooLow) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -3951,7 +4153,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, CreateGroupSetsVisualData) { +TEST_P(TabStripModelTest, CreateGroupSetsVisualData) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); tab_groups::ColorLabelMap all_colors = tab_groups::GetTabGroupColorLabelMap(); @@ -3974,7 +4180,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, SetVisualDataForGroup) { +TEST_P(TabStripModelTest, SetVisualDataForGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 1); @@ -3991,7 +4201,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, VisualDataChangeNotifiesObservers) { +TEST_P(TabStripModelTest, VisualDataChangeNotifiesObservers) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); MockTabStripModelObserver observer; @@ -4016,7 +4230,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ObserverCanBeDestroyedEarly) { +TEST_P(TabStripModelTest, ObserverCanBeDestroyedEarly) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); @@ -4026,7 +4240,11 @@ } } -TEST_F(TabStripModelTest, MovingTabToStartOfGroupDoesNotChangeGroup) { +TEST_P(TabStripModelTest, MovingTabToStartOfGroupDoesNotChangeGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4041,7 +4259,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingTabToMiddleOfGroupDoesNotChangeGroup) { +TEST_P(TabStripModelTest, MovingTabToMiddleOfGroupDoesNotChangeGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4056,7 +4278,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingTabToEndOfGroupDoesNotChangeGroup) { +TEST_P(TabStripModelTest, MovingTabToEndOfGroupDoesNotChangeGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4071,7 +4297,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingTabOutsideOfGroupToStartOfTabstripClearsGroup) { +TEST_P(TabStripModelTest, MovingTabOutsideOfGroupToStartOfTabstripClearsGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4086,7 +4316,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingTabOutsideOfGroupToEndOfTabstripClearsGroup) { +TEST_P(TabStripModelTest, MovingTabOutsideOfGroupToEndOfTabstripClearsGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4101,7 +4335,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingTabBetweenUngroupedTabsClearsGroup) { +TEST_P(TabStripModelTest, MovingTabBetweenUngroupedTabsClearsGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4116,7 +4354,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingUngroupedTabBetweenGroupsDoesNotAssignGroup) { +TEST_P(TabStripModelTest, MovingUngroupedTabBetweenGroupsDoesNotAssignGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4132,8 +4374,12 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, +TEST_P(TabStripModelTest, MovingUngroupedTabBetweenGroupAndUngroupedDoesNotAssignGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -4148,8 +4394,12 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, +TEST_P(TabStripModelTest, MovingUngroupedTabBetweenUngroupedAndGroupDoesNotAssignGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -4164,8 +4414,12 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, +TEST_P(TabStripModelTest, MovingGroupMemberBetweenTwoDifferentGroupsClearsGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 6); @@ -4183,8 +4437,12 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, +TEST_P(TabStripModelTest, MovingSingleTabGroupBetweenTwoGroupsDoesNotClearGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 5); @@ -4202,7 +4460,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingUngroupedTabIntoGroupSetsGroup) { +TEST_P(TabStripModelTest, MovingUngroupedTabIntoGroupSetsGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4217,7 +4479,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MovingGroupedTabIntoGroupChangesGroup) { +TEST_P(TabStripModelTest, MovingGroupedTabIntoGroupChangesGroup) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4233,7 +4499,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveWebContentsAtCorrectlyRemovesGroupEntries) { +TEST_P(TabStripModelTest, MoveWebContentsAtCorrectlyRemovesGroupEntries) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4249,7 +4519,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveWebContentsAtCorrectlySendsGroupChangedEvent) { +TEST_P(TabStripModelTest, MoveWebContentsAtCorrectlySendsGroupChangedEvent) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4275,7 +4549,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, MoveWebContentsAtCorrectlySendsGroupClearedEvent) { +TEST_P(TabStripModelTest, MoveWebContentsAtCorrectlySendsGroupClearedEvent) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4303,7 +4581,7 @@ // Ensure that the opener for a tab never refers to a dangling WebContents. // Regression test for crbug.com/1092308. -TEST_F(TabStripModelTest, DanglingOpener) { +TEST_P(TabStripModelTest, DanglingOpener) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -4363,7 +4641,7 @@ // Sanity check to ensure that the "Move Tabs to Window" command talks to // the delegate correctly. -TEST_F(TabStripModelTest, MoveTabsToNewWindow) { +TEST_P(TabStripModelTest, MoveTabsToNewWindow) { TabToWindowTestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 3); @@ -4389,7 +4667,11 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, SurroundingGroupAtIndex) { +TEST_P(TabStripModelTest, SurroundingGroupAtIndex) { + if (GetParam()) { + GTEST_SKIP(); + } + TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 4); @@ -4406,7 +4688,7 @@ strip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ActivateRecordsStartTime) { +TEST_P(TabStripModelTest, ActivateRecordsStartTime) { TestTabStripModelDelegate delegate; TabStripModel strip(&delegate, profile()); PrepareTabs(&strip, 2); @@ -4437,7 +4719,7 @@ EXPECT_TRUE(has_tab_switch_start_time(1)); } -TEST_F(TabStripModelTest, ToggleSiteMuted) { +TEST_P(TabStripModelTest, ToggleSiteMuted) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -4473,7 +4755,7 @@ tabstrip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ToggleSiteMutedWithLessSpecificRule) { +TEST_P(TabStripModelTest, ToggleSiteMutedWithLessSpecificRule) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -4523,7 +4805,7 @@ tabstrip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ToggleSiteMutedWithOtherDisjointRule) { +TEST_P(TabStripModelTest, ToggleSiteMutedWithOtherDisjointRule) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -4569,7 +4851,7 @@ tabstrip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ToggleSiteMutedWithDifferentDefault) { +TEST_P(TabStripModelTest, ToggleSiteMutedWithDifferentDefault) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -4602,7 +4884,7 @@ tabstrip.CloseAllTabs(); } -TEST_F(TabStripModelTest, ToggleMuteUnmuteMultipleSites) { +TEST_P(TabStripModelTest, ToggleMuteUnmuteMultipleSites) { TestTabStripModelDelegate delegate; TabStripModel tabstrip(&delegate, profile()); EXPECT_TRUE(tabstrip.empty()); @@ -4637,7 +4919,7 @@ tabstrip.CloseAllTabs(); } -TEST_F(TabStripModelTest, AppendTab) { +TEST_P(TabStripModelTest, AppendTab) { TestTabStripModelDelegate delegate; std::unique_ptr<TabStripModel> tabstrip = std::make_unique<TabStripModel>(&delegate, profile()); @@ -4689,3 +4971,5 @@ EXPECT_EQ(tab_model_with_foreground_false_ptr->owning_model(), tabstrip.get()); } + +INSTANTIATE_TEST_SUITE_P(All, TabStripModelTest, ::testing::Bool());
diff --git a/chrome/browser/ui/tabs/unpinned_tab_collection.cc b/chrome/browser/ui/tabs/unpinned_tab_collection.cc index 07a39f12..b1e7a8de 100644 --- a/chrome/browser/ui/tabs/unpinned_tab_collection.cc +++ b/chrome/browser/ui/tabs/unpinned_tab_collection.cc
@@ -117,6 +117,22 @@ impl_->CloseTab(tab_model); } +std::optional<size_t> +UnpinnedTabCollection::GetDirectChildIndexOfCollectionContainingTab( + TabModel* tab_model) const { + if (tab_model->GetParentCollection(GetPassKey()) == this) { + return GetIndexOfTab(tab_model).value(); + } else { + TabCollection* parent_collection = + tab_model->GetParentCollection(GetPassKey()); + while (parent_collection && !ContainsCollection(parent_collection)) { + parent_collection = parent_collection->GetParentCollection(); + } + + return GetIndexOfCollection(parent_collection); + } +} + bool UnpinnedTabCollection::ContainsTab(TabModel* tab_model) const { return impl_->ContainsTab(tab_model); } @@ -131,7 +147,7 @@ } std::optional<size_t> UnpinnedTabCollection::GetIndexOfTabRecursive( - TabModel* tab_model) const { + const TabModel* tab_model) const { size_t current_index = 0; // If the child is a `tab_model` check if it is the the desired tab, otherwise @@ -180,6 +196,11 @@ return removed_tab_model; } +std::optional<size_t> UnpinnedTabCollection::GetIndexOfTab( + TabModel* tab_model) const { + return impl_->GetIndexOfTab(tab_model); +} + size_t UnpinnedTabCollection::ChildCount() const { return impl_->GetChildrenCount(); }
diff --git a/chrome/browser/ui/tabs/unpinned_tab_collection.h b/chrome/browser/ui/tabs/unpinned_tab_collection.h index 50d6c9a0..93fc71fd 100644 --- a/chrome/browser/ui/tabs/unpinned_tab_collection.h +++ b/chrome/browser/ui/tabs/unpinned_tab_collection.h
@@ -54,6 +54,12 @@ // child of the collection. void CloseTab(TabModel* tab_model); + // Returns the direct child index of the collection containing the tab or the + // direct child index of the tab if it is a direct child of the unpinned + // collection. + std::optional<size_t> GetDirectChildIndexOfCollectionContainingTab( + TabModel* tab_model) const; + // Explicit tab group related operations. // Adds a group to the collection at a particular index. void AddTabGroup(std::unique_ptr<TabGroupTabCollection> group, size_t index); @@ -85,7 +91,7 @@ bool ContainsCollection(TabCollection* collection) const override; std::optional<size_t> GetIndexOfTabRecursive( - TabModel* tab_model) const override; + const TabModel* tab_model) const override; std::optional<size_t> GetIndexOfCollection( TabCollection* collection) const override; @@ -101,6 +107,9 @@ size_t TabCountRecursive() const override; private: + // Return the direct child index of a tab + std::optional<size_t> GetIndexOfTab(TabModel* tab_model) const; + // Underlying implementation for the storage of children. std::unique_ptr<TabCollectionStorage> impl_; };
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index ba46618..16c2971 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -1550,6 +1550,13 @@ } LogMenuAction(MENU_ACTION_SHOW_PERFORMANCE_SETTINGS); break; + case IDC_SET_BROWSER_AS_DEFAULT: + if (!uma_action_recorded_) { + base::UmaHistogramMediumTimes( + "WrenchMenu.TimeToAction.SetBrowserAsDefault", delta); + } + LogMenuAction(MENU_ACTION_SET_BROWSER_AS_DEFAULT); + break; default: { if (IsOtherProfileCommand(command_id)) { if (!uma_action_recorded_) {
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h index 307c007..75412101 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.h +++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -108,6 +108,7 @@ MENU_ACTION_SHOW_READING_MODE_SIDE_PANEL = 85, MENU_ACTION_SHOW_SAFETY_HUB = 86, MENU_ACTION_SHOW_PASSWORD_CHECKUP = 87, + MENU_ACTION_SET_BROWSER_AS_DEFAULT = 88, LIMIT_MENU_ACTION };
diff --git a/chrome/browser/ui/views/content_setting_site_row_view.cc b/chrome/browser/ui/views/content_setting_site_row_view.cc index b6ec152..79c0caf8 100644 --- a/chrome/browser/ui/views/content_setting_site_row_view.cc +++ b/chrome/browser/ui/views/content_setting_site_row_view.cc
@@ -84,7 +84,7 @@ const favicon_base::FaviconRawBitmapResult& favicon_result) { if (favicon_result.is_valid()) { favicon_->SetImage(ui::ImageModel::FromImage( - gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->front(), + gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->data(), favicon_result.bitmap_data->size()))); } else { favicon_->SetImage(ui::ImageModel::FromVectorIcon(
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_win.cc b/chrome/browser/ui/views/frame/browser_frame_view_win.cc index d863b9f..1563d50 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_win.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_win.cc
@@ -317,10 +317,14 @@ // At the window corners the resize area is not actually bigger, but the 16 // pixels at the end of the top and bottom edges trigger diagonal resizing. constexpr int kResizeCornerWidth = 16; + + const int top_border_thickness = features::IsChromeRefresh2023() + ? GetLayoutConstant(TAB_STRIP_PADDING) + : FrameTopBorderThickness(false); + int window_component = GetHTComponentForFrame( - point, gfx::Insets::TLBR(GetLayoutConstant(TAB_STRIP_PADDING), 0, 0, 0), - GetLayoutConstant(TAB_STRIP_PADDING), - kResizeCornerWidth - FrameBorderThickness(), + point, gfx::Insets::TLBR(top_border_thickness, 0, 0, 0), + top_border_thickness, kResizeCornerWidth - FrameBorderThickness(), frame()->widget_delegate()->CanResize()); int frame_component = frame()->client_view()->NonClientHitTest(point); @@ -496,7 +500,7 @@ // default. When maximized, the OS sizes the window such that the border // extends beyond the screen edges. In that case, we must return the // default value. - const int kTopResizeFrameArea = 0; + const int kTopResizeFrameArea = features::IsChromeRefresh2023() ? 0 : 5; return kTopResizeFrameArea; }
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc index e0791571..70ca191 100644 --- a/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc
@@ -129,7 +129,7 @@ AddChildView(std::make_unique<DeviceEntryButton>( base::BindRepeating(&MediaItemUIFooterView::OnDeviceSelected, base::Unretained(this), tag), - device_entry->icon(), + &device_entry->icon(), base::UTF8ToUTF16(device_entry->device_name()))); device_entry_button->set_tag(tag); device_entry_button->SetProperty(
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.cc b/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.cc index 97634fa8a..e4806059 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.cc +++ b/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.cc
@@ -56,15 +56,15 @@ // foreground_color_id is only set for CastDeviceEntryViewAsh. std::unique_ptr<views::ImageView> CreateIconView( - const gfx::VectorIcon* icon, + const gfx::VectorIcon& icon, std::optional<ui::ColorId> foreground_color_id = std::nullopt) { auto icon_view = std::make_unique<views::ImageView>(); if (foreground_color_id.has_value()) { icon_view->SetImage(ui::ImageModel::FromVectorIcon( - *icon, foreground_color_id.value(), kDeviceIconSize)); + icon, foreground_color_id.value(), kDeviceIconSize)); } else { icon_view->SetImage(ui::ImageModel::FromVectorIcon( - *icon, gfx::kPlaceholderColor, kDeviceIconSize)); + icon, gfx::kPlaceholderColor, kDeviceIconSize)); } icon_view->SetBorder(views::CreateEmptyBorder(kDeviceIconBorder)); return icon_view; @@ -77,18 +77,18 @@ if (icon == global_media_controls::mojom::IconType::kThrobber) { return media_router::CreateThrobber(); } - return CreateIconView(&GetVectorIcon(icon), foreground_color_id); + return CreateIconView(GetVectorIcon(icon), foreground_color_id); } std::unique_ptr<views::ImageView> GetAudioDeviceIcon() { - return CreateIconView(&vector_icons::kHeadsetIcon); + return CreateIconView(vector_icons::kHeadsetIcon); } } // namespace DeviceEntryUI::DeviceEntryUI(const std::string& raw_device_id, const std::string& device_name, - const gfx::VectorIcon* icon, + const gfx::VectorIcon& icon, const std::string& subtext) : raw_device_id_(raw_device_id), device_name_(device_name), icon_(icon) {} @@ -100,12 +100,12 @@ SkColor background_color, const std::string& raw_device_id, const std::string& device_name) - : DeviceEntryUI(raw_device_id, device_name, &vector_icons::kHeadsetIcon), + : DeviceEntryUI(raw_device_id, device_name, vector_icons::kHeadsetIcon), HoverButton(std::move(callback), GetAudioDeviceIcon(), base::UTF8ToUTF16(device_name)) { ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(), - subtitle(), icon_, foreground_color, background_color); + subtitle(), &icon(), foreground_color, background_color); SetFocusBehavior(views::View::FocusBehavior::ALWAYS); views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::ON); @@ -141,7 +141,7 @@ views::InkDrop::Get(this)->SetBaseColor(foreground_color); ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(), - subtitle(), icon_, foreground_color, background_color); + subtitle(), &icon(), foreground_color, background_color); // Reapply highlight formatting as some effects rely on these colors. SetHighlighted(is_highlighted_); @@ -159,7 +159,7 @@ SkColor foreground_color, SkColor background_color, const global_media_controls::mojom::DevicePtr& device) - : DeviceEntryUI(device->id, device->name, &GetVectorIcon(device->icon)), + : DeviceEntryUI(device->id, device->name, GetVectorIcon(device->icon)), HoverButton(std::move(callback), CreateIconView(device->icon), base::UTF8ToUTF16(device->name), @@ -195,7 +195,7 @@ background_color); } else { ChangeEntryColor(static_cast<views::ImageView*>(icon_view()), title(), - subtitle(), icon_, foreground_color, background_color); + subtitle(), &icon(), foreground_color, background_color); } } @@ -211,7 +211,7 @@ ui::ColorId foreground_color_id, ui::ColorId background_color_id, const global_media_controls::mojom::DevicePtr& device) - : DeviceEntryUI(device->id, device->name, &GetVectorIcon(device->icon)), + : DeviceEntryUI(device->id, device->name, GetVectorIcon(device->icon)), HoverButton(std::move(callback), CreateIconView(device->icon, foreground_color_id), base::UTF8ToUTF16(device->name)),
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h b/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h index 3f80f93..4caf9e1 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h +++ b/chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h
@@ -21,14 +21,14 @@ public: DeviceEntryUI(const std::string& raw_device_id, const std::string& device_name, - const gfx::VectorIcon* icon_, + const gfx::VectorIcon& icon, const std::string& subtext = ""); DeviceEntryUI(const DeviceEntryUI&) = delete; DeviceEntryUI& operator=(const DeviceEntryUI&) = delete; virtual ~DeviceEntryUI() = default; - const gfx::VectorIcon* icon() const { return icon_; } + const gfx::VectorIcon& icon() const { return *icon_; } const std::string& raw_device_id() const { return raw_device_id_; } const std::string& device_name() const { return device_name_; } @@ -42,7 +42,7 @@ const std::string raw_device_id_; const std::string device_name_; bool is_highlighted_ = false; - const raw_ptr<const gfx::VectorIcon> icon_; + const raw_ref<const gfx::VectorIcon> icon_; }; class AudioDeviceEntryView : public DeviceEntryUI, public HoverButton {
diff --git a/chrome/browser/ui/views/infobars/default_browser_infobar_interactive_uitest.cc b/chrome/browser/ui/views/infobars/default_browser_infobar_interactive_uitest.cc index 5b78cbbb..271119c 100644 --- a/chrome/browser/ui/views/infobars/default_browser_infobar_interactive_uitest.cc +++ b/chrome/browser/ui/views/infobars/default_browser_infobar_interactive_uitest.cc
@@ -52,8 +52,7 @@ "settings-default-browser-page", "cr-button"}; } // namespace -class DefaultBrowserInfobarInteractiveTest - : public WebUiInteractiveTestMixin<InteractiveBrowserTest> { +class DefaultBrowserInfobarInteractiveTest : public InteractiveBrowserTest { public: void SetUp() override { scoped_feature_list_.InitAndDisableFeature( @@ -62,15 +61,6 @@ InteractiveBrowserTest::SetUp(); } - ConfirmInfoBar* GetActiveInfoBar() { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - infobars::ContentInfoBarManager* infobar_manager = - infobars::ContentInfoBarManager::FromWebContents(web_contents); - CHECK(infobar_manager); - return static_cast<ConfirmInfoBar*>(infobar_manager->infobars()[0]); - } - private: base::test::ScopedFeatureList scoped_feature_list_; }; @@ -85,7 +75,7 @@ } class DefaultBrowserInfobarWithRefreshInteractiveTest - : public DefaultBrowserInfobarInteractiveTest { + : public WebUiInteractiveTestMixin<InteractiveBrowserTest> { public: void SetUp() override { scoped_feature_list_.InitAndEnableFeatureWithParameters( @@ -142,15 +132,8 @@ InSameContext(EnsureNotPresent(ConfirmInfoBar::kInfoBarElementId))); } -// TODO(crbug.com/335474941): Flaky on Windows. -#if BUILDFLAG(IS_WIN) -#define MAYBE_RemovesAllBrowserPromptsOnAccept \ - DISABLED_RemovesAllBrowserPromptsOnAccept -#else -#define MAYBE_RemovesAllBrowserPromptsOnAccept RemovesAllBrowserPromptsOnAccept -#endif IN_PROC_BROWSER_TEST_F(DefaultBrowserInfobarWithRefreshInteractiveTest, - MAYBE_RemovesAllBrowserPromptsOnAccept) { + RemovesAllBrowserPromptsOnAccept) { DefaultBrowserPromptManager::GetInstance()->MaybeShowPrompt(); RunTestSequence( WaitForShow(ConfirmInfoBar::kInfoBarElementId), FlushEvents(),
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc index 09ec464..9170aa9 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.cc
@@ -109,20 +109,13 @@ // Need to make element visible or calls to show IPH will fail. SetVisible(true); - const base::Feature* feature = nullptr; - if (blocking_status_ != CookieBlocking3pcdStatus::kNotIn3pcd) { - // UB reminder IPH in 3PCD experiment. - feature = &feature_engagement::kIPH3pcdUserBypassFeature; - } else if (should_highlight_) { - // UB IPH when icon should be highlighted. - feature = &feature_engagement::kIPHCookieControlsFeature; - } else { - // In all other cases return without trying to show IPH. + if (blocking_status_ != CookieBlocking3pcdStatus::kNotIn3pcd || + !should_highlight_) { return false; } - CHECK(feature); - user_education::FeaturePromoParams params(*feature); + user_education::FeaturePromoParams params( + feature_engagement::kIPHCookieControlsFeature); params.close_callback = base::BindOnce(&CookieControlsIconView::OnIPHClosed, weak_ptr_factory_.GetWeakPtr()); if (!browser_->window()->MaybeShowFeaturePromo(std::move(params))) { @@ -135,9 +128,7 @@ bool CookieControlsIconView::IsManagedIPHActive() const { CHECK(browser_->window()); return browser_->window()->IsFeaturePromoActive( - feature_engagement::kIPH3pcdUserBypassFeature) || - browser_->window()->IsFeaturePromoActive( - feature_engagement::kIPHCookieControlsFeature); + feature_engagement::kIPHCookieControlsFeature); } void CookieControlsIconView::OnIPHClosed() { @@ -268,8 +259,6 @@ CHECK(browser_->window()); CHECK(ShouldBeVisible()); browser_->window()->CloseFeaturePromo( - feature_engagement::kIPH3pcdUserBypassFeature); - browser_->window()->CloseFeaturePromo( feature_engagement::kIPHCookieControlsFeature); browser_->window()->NotifyFeatureEngagementEvent( feature_engagement::events::kCookieControlsBubbleShown);
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc index f4920103..07c74ab3 100644 --- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc +++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <vector> + #include "base/feature_list_buildflags.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" @@ -450,45 +451,17 @@ user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)); } -class CookieControlsInteractiveUiWith3pcdUserBypassIphTest - : public CookieControlsInteractiveUiBaseTest { - public: - CookieControlsInteractiveUiWith3pcdUserBypassIphTest() - : CookieControlsInteractiveUiBaseTest( - {feature_engagement::kIPH3pcdUserBypassFeature}) {} - ~CookieControlsInteractiveUiWith3pcdUserBypassIphTest() override = default; -}; - -IN_PROC_BROWSER_TEST_F(CookieControlsInteractiveUiWith3pcdUserBypassIphTest, - ShowAndHide3pcdUbIph) { - BlockThirdPartyCookies(/*use_3pcd=*/true); +IN_PROC_BROWSER_TEST_F(CookieControlsInteractiveUiWithCookieControlsIphTest, + NotShownWhen3pcdEnabled) { + BlockThirdPartyCookies(/*use_3pcd*/ true); + SetHighSiteEngagement(); RunTestSequence( InstrumentTab(kWebContentsElementId), NavigateWebContents(kWebContentsElementId, third_party_cookie_page_url()), - InAnyContext(WaitForShow( - user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)), - PressButton(user_education::HelpBubbleView::kCloseButtonIdForTesting), - WaitForHide( - user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)); -} - -IN_PROC_BROWSER_TEST_F(CookieControlsInteractiveUiWith3pcdUserBypassIphTest, - Show3pcdUbIphAndOpenCookieControlsViaIcon) { - BlockThirdPartyCookies(/*use_3pcd=*/true); - RunTestSequence( - InstrumentTab(kWebContentsElementId), - NavigateWebContents(kWebContentsElementId, third_party_cookie_page_url()), - // Check that IPH shows, then open cookie controls bubble via icon. - InAnyContext(WaitForShow( - user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)), - PressButton(kCookieControlsIconElementId), - // Cookie controls bubble should show and IPH should close. - InAnyContext( - WaitForShow(CookieControlsBubbleView::kCookieControlsBubble)), + // Check that the IPH does not show. EnsureNotPresent( user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)); } - // Opening the feedback dialog on CrOS & LaCrOS open a system level dialog, // which cannot be easily tested here. Instead, LaCrOS has a separate feedback // browser test which gives some coverage.
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc index 2ab7ec3c..6cfef0d6 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_two_origins_view.cc
@@ -219,7 +219,7 @@ if (favicon_result.is_valid()) { favicon_right_->SetImage(ui::ImageModel::FromImage( - gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->front(), + gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->data(), favicon_result.bitmap_data->size()))); } MaybeShow(); @@ -233,7 +233,7 @@ if (favicon_result.is_valid()) { favicon_left_->SetImage(ui::ImageModel::FromImage( - gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->front(), + gfx::Image::CreateFrom1xPNGBytes(favicon_result.bitmap_data->data(), favicon_result.bitmap_data->size()))); } MaybeShow();
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index f43dec09..799f5e1 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -324,7 +324,10 @@ // Height should go to the bottom of the tab for the crashed tab animation // to pop out of the bottom. favicon_bounds.set_y(contents_rect.y() + - Center(gfx::kFaviconSize, gfx::kFaviconSize)); + Center(features::IsChromeRefresh2023() + ? gfx::kFaviconSize + : contents_rect.height(), + gfx::kFaviconSize)); if (center_icon_) { // When centering the favicon, the favicon is allowed to escape the normal // contents rect.
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index fe75f65..96b4e6fd 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -14,6 +14,7 @@ #include <utility> #include <vector> +#include "base/check.h" #include "base/compiler_specific.h" #include "base/containers/adapters.h" #include "base/containers/contains.h" @@ -28,6 +29,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" +#include "base/not_fatal_until.h" #include "base/numerics/safe_conversions.h" #include "base/observer_list.h" #include "base/ranges/algorithm.h" @@ -297,17 +299,21 @@ } } - DCHECK(!dragging_views.empty()); - DCHECK(base::Contains(dragging_views, source)); + CHECK(!dragging_views.empty(), base::NotFatalUntil::M128) + << "Dragging views cannot be empty during drag initialization."; + CHECK(base::Contains(dragging_views, source), base::NotFatalUntil::M128) + << "Source must be part of dragging views."; // Delete the existing DragController before creating a new one. We do this // as creating the DragController remembers the WebContents delegates and we // need to make sure the existing DragController isn't still a delegate. drag_controller_.reset(); - DCHECK(event.type() == ui::ET_MOUSE_PRESSED || + CHECK((event.type() == ui::ET_MOUSE_PRESSED || event.type() == ui::ET_GESTURE_TAP_DOWN || - event.type() == ui::ET_GESTURE_SCROLL_BEGIN); + event.type() == ui::ET_GESTURE_SCROLL_BEGIN), + base::NotFatalUntil::M128) + << "Event type must be suitable for starting a drag."; drag_controller_ = std::make_unique<TabDragController>(); @@ -399,8 +405,12 @@ void OwnDragController( std::unique_ptr<TabDragController> controller) override { - DCHECK(controller); - DCHECK(!drag_controller_); + CHECK(controller, base::NotFatalUntil::M128) + << "The provided TabDragController is null, which is not expected."; + + CHECK(!drag_controller_, base::NotFatalUntil::M128) + << "Attempting to own a new drag controller while one already exists."; + drag_controller_ = std::move(controller); if (drag_controller_set_callback_) { std::move(drag_controller_set_callback_).Run(drag_controller_.get()); @@ -504,9 +514,8 @@ const int first_dragged_tab_model_index = tab_strip_->GetModelIndexOf(dragged_views[group.has_value() ? 1 : 0]) .value(); - const int index = - CalculateInsertionIndex(dragged_bounds, first_dragged_tab_model_index, - num_dragged_tabs, std::move(group)); + const int index = CalculateInsertionIndex( + dragged_bounds, first_dragged_tab_model_index, num_dragged_tabs, group); const Tab* last_visible_tab = tab_strip_->GetLastVisibleTab(); int last_insertion_point = @@ -522,7 +531,8 @@ std::vector<gfx::Rect> CalculateBoundsForDraggedViews( const std::vector<raw_ptr<TabSlotView, VectorExperimental>>& views) override { - DCHECK(!views.empty()); + CHECK(!views.empty(), base::NotFatalUntil::M128) + << "The views vector must not be empty."; std::vector<gfx::Rect> bounds; const int overlap = TabStyle::Get()->GetTabOverlap(); @@ -539,8 +549,11 @@ void SetBoundsForDrag( const std::vector<raw_ptr<TabSlotView, VectorExperimental>>& views, const std::vector<gfx::Rect>& bounds) override { + CHECK(!views.empty() || !bounds.empty(), base::NotFatalUntil::M128) + << "Views and bounds cannot both be empty."; tab_strip_->tab_container_->CancelAnimation(); - DCHECK_EQ(views.size(), bounds.size()); + CHECK_EQ(views.size(), bounds.size(), base::NotFatalUntil::M128) + << "The sizes of views and bounds must match."; for (size_t i = 0; i < views.size(); ++i) { views[i]->SetBoundsRect(bounds[i]); } @@ -553,9 +566,9 @@ // Reset the layout size as we've effectively laid out a different size. // This ensures a layout happens after the drag is done. tab_strip_->tab_container_->InvalidateIdealBounds(); - if (views.at(0)->group().has_value()) { + if (views[0]->group().has_value()) { tab_strip_->tab_container_->UpdateTabGroupVisuals( - views.at(0)->group().value()); + views[0]->group().value()); } } @@ -568,7 +581,8 @@ // No tabs should be dragging at this point. for (int i = 0; i < GetTabCount(); ++i) { - DCHECK(!GetTabAt(i)->dragging()); + CHECK(!GetTabAt(i)->dragging(), base::NotFatalUntil::M128) + << "A tab is still marked as dragging when starting a new drag."; } tab_strip_->tab_container_->CompleteAnimationAndLayout(); @@ -640,7 +654,8 @@ const gfx::Point& location, bool initial_drag) override { std::vector<gfx::Rect> bounds = CalculateBoundsForDraggedViews(views); - DCHECK_EQ(views.size(), bounds.size()); + CHECK_EQ(views.size(), bounds.size(), base::NotFatalUntil::M128) + << "The sizes of views and bounds must match in LayoutDraggedViewsAt."; // The index of `source_view` in the TabStrip's viewmodel. std::optional<int> source_view_model_index = GetIndexOf(source_view); @@ -824,7 +839,9 @@ } } - CHECK_NE(min_distance_index, -1); + CHECK_NE(min_distance_index, -1) + << "No valid insertion index found for the dragged tab, which " + "indicates a potential logic error in tab placement calculations."; // When moving a tab within a tabstrip, the target index is expressed as if // the tabs are not in the tabstrip, i.e. it acts like the tabs are first @@ -996,7 +1013,8 @@ RemoveChildViewT(base::to_address(tab_container_)); RemoveChildViewT(base::to_address(drag_context_)); - CHECK(!IsInObserverList()); + CHECK(!IsInObserverList()) + << "TabStrip should not be in any observer lists at destruction."; } void TabStrip::SetAvailableWidthCallback( @@ -1066,7 +1084,8 @@ } void TabStrip::AddTabAt(int model_index, TabRendererData data) { - DCHECK(IsValidModelIndex(model_index)); + CHECK(IsValidModelIndex(model_index), base::NotFatalUntil::M128) + << "Attempted to add a tab with an invalid model index."; const bool pinned = data.pinned; Tab* tab = tab_container_->AddTab( @@ -1086,10 +1105,10 @@ observer.OnTabAdded(model_index); } - // At the start of AddTabAt() the model and tabs are out sync. Any queries to - // find a tab given a model index can go off the end of |tabs_|. As such, it - // is important that we complete the drag *after* adding the tab so that the - // model and tabstrip are in sync. + // At the start of AddTabAt() the model and tabs are out of sync. Any queries + // to find a tab given a model index can go off the end of |tabs_|. As such, + // it is important that we complete the drag *after* adding the tab so that + // the model and tabstrip are in sync. drag_context_->TabWasAdded(); Profile* profile = controller_->GetProfile(); @@ -1114,7 +1133,9 @@ void TabStrip::MoveTab(int from_model_index, int to_model_index, TabRendererData data) { - DCHECK_GT(GetTabCount(), 0); + CHECK_GT(GetTabCount(), 0, base::NotFatalUntil::M128) + << "The tab strip must contain at least one tab to perform a move " + "operation."; Tab* moving_tab = tab_at(from_model_index); moving_tab->SetData(std::move(data)); @@ -1134,7 +1155,10 @@ // OnTabWillBeRemoved should have ended any ongoing drags containing // `contents` already - unless the call is coming from inside the house! (i.e. // the TabDragController is doing the removing as part of reverting a drag) - DCHECK(drag_context_->CanRemoveTabIfDragging(contents)); + CHECK(drag_context_->CanRemoveTabIfDragging(contents), + base::NotFatalUntil::M128) + << "Attempted to remove a tab that could not be removed during drag."; + tab_container_->RemoveTab(model_index, was_active); UpdateHoverCard(nullptr, HoverCardUpdateType::kTabRemoved); @@ -1262,8 +1286,11 @@ } void TabStrip::SetSelection(const ui::ListSelectionModel& new_selection) { - DCHECK(new_selection.active().has_value()) + // This CHECK ensures there is always an active tab to maintain UI + // consistency. + CHECK(new_selection.active().has_value(), base::NotFatalUntil::M128) << "We should never transition to a state where no tab is active."; + Tab* const new_active_tab = tab_at(new_selection.active().value()); Tab* const old_active_tab = selected_tabs_.active().has_value() ? tab_at(selected_tabs_.active().value()) @@ -1687,9 +1714,11 @@ // Check that the source is either a valid tab or a tab group header, which // are the only valid drag targets. - DCHECK(GetModelIndexOf(source).has_value() || - source->GetTabSlotViewType() == - TabSlotView::ViewType::kTabGroupHeader); + CHECK(GetModelIndexOf(source).has_value() || + source->GetTabSlotViewType() == + TabSlotView::ViewType::kTabGroupHeader, + base::NotFatalUntil::M128) + << "Drag source must be a valid tab or a tab group header."; drag_context_->MaybeStartDrag(source, event, original_selection); has_reported_tab_drag_metrics_ = false; @@ -1871,9 +1900,8 @@ // TabStrip, views::View overrides: views::SizeBounds TabStrip::GetAvailableSize(const views::View* child) const { - // We can only reach here if SetAvailableWidthCallback() was never called, - // e.g. if tab scrolling is disabled. Defer to our parent. - DCHECK(child == base::to_address(tab_container_)); + CHECK(child == base::to_address(tab_container_), base::NotFatalUntil::M128) + << "The child view does not match the expected tab_container_ address."; return parent()->GetAvailableSize(this); } @@ -1994,7 +2022,9 @@ if (ui::Clipboard::IsSupportedClipboardBuffer( ui::ClipboardBuffer::kSelection)) { ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); - CHECK(clipboard); + CHECK(clipboard) + << "Clipboard instance is not available, cannot proceed with " + "middle mouse button action."; std::u16string clipboard_text; clipboard->ReadText(ui::ClipboardBuffer::kSelection, /* data_dst = */ nullptr, &clipboard_text); @@ -2123,7 +2153,8 @@ } void TabStrip::ShiftTabRelative(Tab* tab, int offset) { - DCHECK_EQ(1, std::abs(offset)); + CHECK_EQ(1, std::abs(offset), base::NotFatalUntil::M128) + << "Offset must be 1 or -1 to shift tab left or right."; const std::optional<int> maybe_start_index = GetModelIndexOf(tab); if (!maybe_start_index.has_value()) { return; @@ -2193,7 +2224,8 @@ void TabStrip::ShiftGroupRelative(const tab_groups::TabGroupId& group, int offset) { - DCHECK_EQ(1, std::abs(offset)); + CHECK_EQ(1, std::abs(offset), base::NotFatalUntil::M128) + << "Offset must be 1 or -1 to shift the group left or right."; gfx::Range tabs_in_group = controller_->ListTabsInGroup(group); const int start_index = tabs_in_group.start(); @@ -2213,7 +2245,8 @@ std::optional<tab_groups::TabGroupId> target_group = tab_at(index_of_skipped_over_tab)->group(); if (target_group.has_value()) { - CHECK_NE(target_group.value(), group); + CHECK_NE(target_group.value(), group) + << "The target group must be different from the current group to move."; } const int num_skipped_tabs = @@ -2250,7 +2283,8 @@ ui::MenuSourceType source_type) { // We are only intended to be installed as a context-menu handler for tabs, so // this cast should be safe. - DCHECK(views::IsViewClass<Tab>(source)); + CHECK(views::IsViewClass<Tab>(source), base::NotFatalUntil::M128) + << "The source must be a Tab class."; Tab* const tab = static_cast<Tab*>(source); if (tab->closing()) { return;
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc index f7fdd7f..7a15b42e 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -546,16 +546,6 @@ .SetCustomActionDismissText( IDS_COOKIE_CONTROLS_PROMO_CLOSE_BUTTON_TEXT))); - // kIPH3pcdUserBypassFeature: - registry.RegisterFeature(std::move( - FeaturePromoSpecification::CreateForToastPromo( - feature_engagement::kIPH3pcdUserBypassFeature, - kCookieControlsIconElementId, IDS_3PCD_USER_BYPASS_PROMO_TEXT, - IDS_3PCD_USER_BYPASS_PROMO_SCREENREADER, - FeaturePromoSpecification::AcceleratorInfo()) - .SetBubbleArrow(HelpBubbleArrow::kTopRight) - .SetBubbleTitleText(IDS_3PCD_USER_BYPASS_PROMO_TITLE))); - // kIPHReadingListDiscoveryFeature: if (features::IsSidePanelPinningEnabled()) { registry.RegisterFeature(
diff --git a/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc b/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc index 54cbdc6..acb97a8 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/a11y/accessibility_section.cc
@@ -902,8 +902,6 @@ {"caretBlinkIntervalDescription", IDS_SETTINGS_CARET_BLINK_INTERVAL_DESCRIPTION}, {"caretBlinkIntervalOff", IDS_SETTINGS_CARET_BLINK_INTERVAL_OFF}, - {"caretBlinkIntervalNormal", IDS_SETTINGS_CARET_BLINK_INTERVAL_NORMAL}, - {"caretBlinkIntervalSlow", IDS_SETTINGS_CARET_BLINK_INTERVAL_SLOW}, {"caretBlinkIntervalFast", IDS_SETTINGS_CARET_BLINK_INTERVAL_FAST}, {"faceGazeCursorAccelerationLabel", IDS_OS_SETTINGS_ACCESSIBILITY_FACEGAZE_CURSOR_ACCELERATION_LABEL},
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/integration_tests/audio_page_interactive_uitest.cc b/chrome/browser/ui/webui/ash/settings/pages/device/integration_tests/audio_page_interactive_uitest.cc index c5023fb..563df97 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/device/integration_tests/audio_page_interactive_uitest.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/device/integration_tests/audio_page_interactive_uitest.cc
@@ -222,9 +222,8 @@ const AudioDevice* audio_device = audio_handler()->GetDeviceFromId(device_id); DCHECK(audio_device); - audio_handler()->SwitchToDevice( - *audio_device, /*notify=*/true, - CrasAudioHandler::DeviceActivateType::ACTIVATE_BY_USER); + audio_handler()->SwitchToDevice(*audio_device, /*notify=*/true, + DeviceActivateType::kActivateByUser); if (audio_device->is_input) { MaybeWaitForInputDevice(device_id); } else {
diff --git a/chrome/browser/ui/webui/ash/user_image_source.cc b/chrome/browser/ui/webui/ash/user_image_source.cc index ecf41dfe..98fae4b 100644 --- a/chrome/browser/ui/webui/ash/user_image_source.cc +++ b/chrome/browser/ui/webui/ash/user_image_source.cc
@@ -84,10 +84,10 @@ gfx::ImageSkia* image = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); float scale = ui::GetScaleForResourceScaleFactor(scale_factor); - scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes); + auto data = base::MakeRefCounted<base::RefCountedBytes>(); gfx::PNGCodec::EncodeBGRASkBitmap(image->GetRepresentation(scale).GetBitmap(), false /* discard transparency */, - &data->data()); + &data->as_vector()); return data; } @@ -114,7 +114,7 @@ } scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes); gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false /* discard transparency */, - &data->data()); + &data->as_vector()); return data; } @@ -143,7 +143,7 @@ scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes); gfx::PNGCodec::EncodeBGRASkBitmap(*user->GetImage().bitmap(), false /* discard transparency */, - &data->data()); + &data->as_vector()); return data; } }
diff --git a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc index 57425947..51c76d9 100644 --- a/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc +++ b/chrome/browser/ui/webui/cr_components/history_embeddings/history_embeddings_handler.cc
@@ -66,7 +66,7 @@ HistoryEmbeddingsServiceFactory::GetForProfile(profile_.get()); // The service is never null. Even tests build and use a service. CHECK(service); - service->Search(query->query, + service->Search(query->query, query->time_range_start, history_embeddings::kSearchResultItemCount.Get(), base::BindOnce(&OnSearchCompleted, std::move(callback))); }
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc index ed846d8a..f11a1291 100644 --- a/chrome/browser/ui/webui/downloads/downloads_ui.cc +++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -165,10 +165,11 @@ {"warningBypassDialogLearnMoreLink", IDS_DOWNLOAD_WARNING_BYPASS_DIALOG_LEARN_MORE_LINK}, {"warningBypassDialogCancel", IDS_CANCEL}, - +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) // ESB Download Row Promo {"esbDownloadRowPromoString", IDS_DOWNLOAD_ROW_ESB_PROMOTION}, {"esbDownloadRowPromoA11y", IDS_DOWNLOAD_ROW_ESB_PROMO_A11Y}, +#endif }; source->AddLocalizedStrings(kStrings); @@ -229,10 +230,12 @@ source->AddLocalizedString("toastDeletedFromHistory", IDS_DOWNLOADS_TOAST_DELETED_FROM_HISTORY); +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) // Download Row ESB Promo: source->AddBoolean( "esbDownloadRowPromo", base::FeatureList::IsEnabled(safe_browsing::kEsbDownloadRowPromo)); +#endif // Build an Accelerator to describe undo shortcut // NOTE: the undo shortcut is also defined in downloads/downloads.html
diff --git a/chrome/browser/ui/webui/extensions/extension_icon_source.cc b/chrome/browser/ui/webui/extensions/extension_icon_source.cc index a80e3f2..0e39174 100644 --- a/chrome/browser/ui/webui/extensions/extension_icon_source.cc +++ b/chrome/browser/ui/webui/extensions/extension_icon_source.cc
@@ -46,7 +46,7 @@ scoped_refptr<base::RefCountedMemory> BitmapToMemory(const SkBitmap* image) { auto image_bytes = base::MakeRefCounted<base::RefCountedBytes>(); - gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_bytes->data()); + gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_bytes->as_vector()); return image_bytes; } @@ -251,8 +251,9 @@ std::move(request->callback).Run(bitmap_result.bitmap_data.get()); ClearData(request_id); } else { - FinalizeImage(ToBitmap(bitmap_result.bitmap_data->front(), - bitmap_result.bitmap_data->size()), request_id); + FinalizeImage(ToBitmap(bitmap_result.bitmap_data->data(), + bitmap_result.bitmap_data->size()), + request_id); } }
diff --git a/chrome/browser/ui/webui/fileicon_source.cc b/chrome/browser/ui/webui/fileicon_source.cc index 5bd039c..2c5a10d 100644 --- a/chrome/browser/ui/webui/fileicon_source.cc +++ b/chrome/browser/ui/webui/fileicon_source.cc
@@ -89,7 +89,7 @@ scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes); gfx::PNGCodec::EncodeBGRASkBitmap( icon->ToImageSkia()->GetRepresentation(scale_factor).GetBitmap(), false, - &icon_data->data()); + &icon_data->as_vector()); std::move(callback).Run(icon_data.get()); } else { @@ -138,7 +138,7 @@ scoped_refptr<base::RefCountedBytes> icon_data(new base::RefCountedBytes); gfx::PNGCodec::EncodeBGRASkBitmap( icon.ToImageSkia()->GetRepresentation(details.scale_factor).GetBitmap(), - false, &icon_data->data()); + false, &icon_data->as_vector()); std::move(details.callback).Run(icon_data.get()); } else {
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index 0b3c1eb..f21d71a 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -577,7 +577,7 @@ IDR_SECURITY_INTERSTITIAL_UI_HTML); } scoped_refptr<base::RefCountedString> html_bytes = new base::RefCountedString; - html_bytes->data().assign(html.begin(), html.end()); + html_bytes->as_string() = html; std::move(callback).Run(html_bytes.get()); }
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc index 195b1e6a..d8b91e7 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -1377,7 +1377,7 @@ } auto image_doodle = new_tab_page::mojom::AllModeImageDoodle::New(); image_doodle->light = MakeImageDoodle( - logo->metadata.type, logo->encoded_image->data(), + logo->metadata.type, logo->encoded_image->as_string(), logo->metadata.mime_type, logo->metadata.animated_url, logo->metadata.width_px, logo->metadata.height_px, "#ffffff", logo->metadata.share_button_x, logo->metadata.share_button_y, @@ -1386,7 +1386,7 @@ logo->metadata.cta_log_url); if (logo->dark_encoded_image) { image_doodle->dark = MakeImageDoodle( - logo->metadata.type, logo->dark_encoded_image->data(), + logo->metadata.type, logo->dark_encoded_image->as_string(), logo->metadata.dark_mime_type, logo->metadata.dark_animated_url, logo->metadata.dark_width_px, logo->metadata.dark_height_px, logo->metadata.dark_background_color,
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index 0df6819..d44e324c 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -460,6 +460,12 @@ {"modulesDummyTitle", IDS_NTP_MODULES_DUMMY_TITLE}, {"modulesFeedTitle", IDS_NTP_MODULES_FEED_TITLE}, {"modulesTodayCalendarHeader", IDS_NTP_MODULES_TODAY_CALENDAR_HEADER}, + {"modulesGoogleCalendarTitle", IDS_NTP_MODULES_GOOGLE_CALENDAR_TITLE}, + {"modulesGoogleCalendarDisableButtonText", + IDS_NTP_MODULES_GOOGLE_CALENDAR_DISABLE_BUTTON_TEXT}, + {"modulesOutlookCalendarTitle", IDS_NTP_MODULES_OUTLOOK_CALENDAR_TITLE}, + {"modulesOutlookCalendarDisableButtonText", + IDS_NTP_MODULES_OUTLOOK_CALENDAR_DISABLE_BUTTON_TEXT}, {"modulesKaleidoscopeTitle", IDS_NTP_MODULES_KALEIDOSCOPE_TITLE}, {"modulesPhotosInfo", IDS_NTP_MODULES_PHOTOS_INFO}, {"modulesPhotosSentence", IDS_NTP_MODULES_PHOTOS_MEMORIES_TITLE},
diff --git a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc index 6e74e2c..7e95371 100644 --- a/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc +++ b/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
@@ -44,10 +44,8 @@ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); scoped_refptr<base::RefCountedMemory> bytes = bundle.LoadDataResourceBytes(resource_id); - base::StringPiece string_piece(reinterpret_cast<const char*>(bytes->front()), - bytes->size()); return ui::ReplaceTemplateExpressions( - string_piece, replacements, + base::as_string_view(*bytes), replacements, /* skip_unexpected_placeholder_check= */ true); }
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index a385abe..870aad36 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -87,10 +87,8 @@ std::string ReplaceTemplateExpressions( const scoped_refptr<base::RefCountedMemory>& bytes, const ui::TemplateReplacements& replacements) { - return ui::ReplaceTemplateExpressions( - base::StringPiece(reinterpret_cast<const char*>(bytes->front()), - bytes->size()), - replacements); + return ui::ReplaceTemplateExpressions(base::as_string_view(*bytes), + replacements); } } // namespace
diff --git a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc index bbe307c..6c8a151 100644 --- a/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc +++ b/chrome/browser/ui/webui/on_device_internals/on_device_internals_ui.cc
@@ -24,7 +24,7 @@ #endif namespace { - +#if !BUILDFLAG(IS_CHROMEOS_ASH) on_device_model::ModelAssets LoadModelAssets(const base::FilePath& model_path) { // This WebUI currently provides no way to dynamically configure the expected // output dimension of the TS model. Since the model is in flux and its output @@ -40,7 +40,7 @@ } return on_device_model::LoadModelAssets(model_paths); } - +#endif } // namespace OnDeviceInternalsUI::OnDeviceInternalsUI(content::WebUI* web_ui) @@ -67,6 +67,16 @@ const base::FilePath& model_path, mojo::PendingReceiver<on_device_model::mojom::OnDeviceModel> model, LoadModelCallback callback) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + // We treat the file path as a UUID on ChromeOS. + base::Uuid uuid = base::Uuid::ParseLowercase(model_path.value()); + if (!uuid.is_valid()) { + std::move(callback).Run( + on_device_model::mojom::LoadModelResult::kFailedToLoadLibrary); + return; + } + GetService().LoadPlatformModel(uuid, std::move(model), std::move(callback)); +#else // Warm the service while assets load in the background. std::ignore = GetService(); base::ThreadPool::PostTaskAndReplyWithResult( @@ -75,6 +85,7 @@ base::BindOnce(&OnDeviceInternalsUI::OnModelAssetsLoaded, weak_ptr_factory_.GetWeakPtr(), std::move(model), std::move(callback))); +#endif } on_device_model::mojom::OnDeviceModelService&
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index a6a2c76..8220870 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -288,7 +288,7 @@ std::string RefCountedMemoryToString( scoped_refptr<base::RefCountedMemory> memory) { - return std::string(memory->front_as<char>(), memory->size()); + return std::string(base::as_string_view(*memory)); } // Fake PwgRasterConverter used in the tests. @@ -322,7 +322,7 @@ return; } - memcpy(memory.mapping.memory(), data->front(), data->size()); + memory.mapping.GetMemoryAsSpan<uint8_t>().copy_from(*data); conversion_settings_ = conversion_settings; bitmap_settings_ = bitmap_settings; std::move(callback).Run(std::move(memory.region));
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 1a1296f31..705accaa 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -730,7 +730,6 @@ return; } DCHECK(data->size()); - DCHECK(data->front()); // After validating |settings|, record metrics. const mojom::RequestPrintPreviewParams* request_params = GetRequestParams();
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc index 54651b6..375729b4 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -409,8 +409,7 @@ base::Value::Dict settings, scoped_refptr<base::RefCountedMemory> data, const std::string& callback_id) override { - ASSERT_EQ(base::StringPiece(data->front_as<const char>(), data->size()), - kTestData); + ASSERT_EQ(base::as_string_view(*data), kTestData); print_called_after_scan_ = true; PrintPreviewHandler::FinishHandleDoPrint(user_action, std::move(settings), data, callback_id);
diff --git a/chrome/browser/ui/webui/sanitized_image_source.cc b/chrome/browser/ui/webui/sanitized_image_source.cc index 163ff18..0f7b0001 100644 --- a/chrome/browser/ui/webui/sanitized_image_source.cc +++ b/chrome/browser/ui/webui/sanitized_image_source.cc
@@ -347,10 +347,10 @@ const bool success = encode_type == RequestAttributes::EncodeType::kWebP ? gfx::WebpCodec::Encode(bitmap, /*quality=*/90, - &encoded->data()) + &encoded->as_vector()) : gfx::PNGCodec::EncodeBGRASkBitmap( bitmap, /*discard_transparency=*/false, - &encoded->data()); + &encoded->as_vector()); return success ? encoded : base::MakeRefCounted<base::RefCountedBytes>(); },
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.cc index b1f764da..c092b9eb 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.cc
@@ -54,6 +54,9 @@ registry->RegisterIntegerPref( prefs::kAccessibilityReadAnythingHighlightColor, 0, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + registry->RegisterListPref( + prefs::kAccessibilityReadAnythingLanguagesEnabled, base::Value::List(), + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); } if (features::IsReadAnythingOmniboxIconEnabled()) { registry->RegisterIntegerPref(
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.h index 914f8a7..022b865 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.h +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_prefs.h
@@ -61,6 +61,11 @@ inline constexpr char kAccessibilityReadAnythingLinksEnabled[] = "settings.a11y.read_anything.links_enabled"; +// List of strings to represent the user's preferred +// languages for the read anything UI. +inline constexpr char kAccessibilityReadAnythingLanguagesEnabled[] = + "settings.a11y.read_anything.languages_enabled"; + } // namespace prefs void RegisterReadAnythingProfilePrefs(
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc index 00bb7f6..58f9b806 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.cc
@@ -274,6 +274,10 @@ features::IsReadAnythingReadAloudEnabled() ? prefs->GetDict(prefs::kAccessibilityReadAnythingVoiceName).Clone() : base::Value::Dict(), + features::IsReadAnythingReadAloudEnabled() + ? prefs->GetList(prefs::kAccessibilityReadAnythingLanguagesEnabled) + .Clone() + : base::Value::List(), highlightGranularity); } @@ -442,6 +446,21 @@ } } +void ReadAnythingUntrustedPageHandler::OnLanguagePrefChange( + const std::string& lang, + bool enabled) { + if (browser_) { + PrefService* prefs = browser_->profile()->GetPrefs(); + ScopedListPrefUpdate update( + prefs, prefs::kAccessibilityReadAnythingLanguagesEnabled); + if (enabled) { + update->Append(lang); + } else { + update->EraseValue(base::Value(lang)); + } + } +} + void ReadAnythingUntrustedPageHandler::OnHighlightGranularityChanged( read_anything::mojom::HighlightGranularity granularity) { if (browser_) {
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h index 935e61f..aadf87d54 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_page_handler.h
@@ -124,6 +124,7 @@ void OnSpeechRateChange(double rate) override; void OnVoiceChange(const std::string& voice, const std::string& lang) override; + void OnLanguagePrefChange(const std::string& lang, bool enabled) override; void OnHighlightGranularityChanged( read_anything::mojom::HighlightGranularity granularity) override; void OnLinkClicked(const ui::AXTreeID& target_tree_id,
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc index a0f7078..c2c1cbb 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc
@@ -82,6 +82,9 @@ {"playDescription", IDS_READING_MODE_PLAY_DESCRIPTION}, {"playLabel", IDS_READING_MODE_PLAY_SPEECH}, {"pauseLabel", IDS_READING_MODE_PAUSE_SPEECH}, + {"stopLabel", IDS_READING_MODE_STOP_SPEECH}, + {"playTooltip", IDS_READING_MODE_PLAY_TOOLTIP}, + {"pauseTooltip", IDS_READING_MODE_PAUSE_TOOLTIP}, {"previousSentenceLabel", IDS_READING_MODE_NAVIGATE_PREVIOUS_SENTENCE}, {"nextSentenceLabel", IDS_READING_MODE_NAVIGATE_NEXT_SENTENCE}, {"moreOptionsLabel", IDS_READING_MODE_MORE_OPTIONS}, @@ -96,6 +99,13 @@ {"readingModeToolbarLabel", IDS_READING_MODE_TOOLBAR_LABEL}, {"readingModeVoicePreviewText", IDS_READING_MODE_VOICE_PREVIEW_STRING}, {"readingModeFontLoadingText", IDS_READING_MODE_FONT_LOADING_STRING}, + {"readingModeLanguageMenu", IDS_READING_MODE_LANGUAGE_MENU}, + {"readingModeLanguageMenuTitle", IDS_READING_MODE_LANGUAGE_MENU_TITLE}, + {"readingModeLanguageMenuClose", IDS_READING_MODE_LANGUAGE_MENU_CLOSE}, + {"readingModeLanguageMenuSearchLabel", + IDS_READING_MODE_LANGUAGE_MENU_SEARCH_LABEL}, + {"readingModeLanguageMenuSearchClear", + IDS_READING_MODE_LANGUAGE_MENU_SEARCH_CLEAR}, }; for (const auto& str : kLocalizedStrings) { webui::AddLocalizedString(source, str.name, str.id);
diff --git a/chrome/browser/ui/webui/test_files_request_filter.cc b/chrome/browser/ui/webui/test_files_request_filter.cc index 5d94301..906a1173 100644 --- a/chrome/browser/ui/webui/test_files_request_filter.cc +++ b/chrome/browser/ui/webui/test_files_request_filter.cc
@@ -43,7 +43,7 @@ &contents)); base::RefCountedString* ref_contents = new base::RefCountedString(); - ref_contents->data() = contents; + ref_contents->as_string() = contents; std::move(callback).Run(ref_contents); }
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc index 04e8979..b7a7542 100644 --- a/chrome/browser/ui/webui/theme_source.cc +++ b/chrome/browser/ui/webui/theme_source.cc
@@ -73,7 +73,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale); gfx::PNGCodec::EncodeBGRASkBitmap( - rep.GetBitmap(), false /* discard transparency */, &data->data()); + rep.GetBitmap(), false /* discard transparency */, &data->as_vector()); } } // namespace
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 22a77036..ef596c7 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -447,6 +447,7 @@ "//chrome/browser/browsing_data:constants", "//chrome/browser/favicon", "//chrome/browser/profiles:profile", + "//chrome/browser/shortcuts", "//chrome/common", "//chrome/common:chrome_features", "//chrome/common:non_code_constants",
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm index c2553ac..6b14fbf 100644 --- a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm +++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm
@@ -52,6 +52,7 @@ #include "cc/paint/paint_flags.h" #import "chrome/browser/mac/dock.h" #include "chrome/browser/shell_integration.h" +#include "chrome/browser/shortcuts/platform_util_mac.h" #include "chrome/browser/web_applications/os_integration/icns_encoder.h" #include "chrome/browser/web_applications/os_integration/os_integration_test_override.h" #include "chrome/browser/web_applications/os_integration/web_app_shortcut.h" @@ -720,7 +721,7 @@ using ResourceIDToImage = std::map<int, NSImageRep*>; -// Generates a map of NSImageReps used by SetWorkspaceIconOnFILEThread and +// Generates a map of NSImageReps used by SetWorkspaceIconOnWorkerThread and // passes it to |io_task|. Since ui::ResourceBundle can only be used on UI // thread, this function also needs to run on UI thread, and the gfx::Images // need to be converted to NSImageReps on the UI thread due to non-thread-safety @@ -734,18 +735,15 @@ std::make_unique<ResourceIDToImage>(); // These resource ID should match to the ones used by - // SetWorkspaceIconOnFILEThread below. + // SetWorkspaceIconOnWorkerThread below. for (int id : {IDR_APPS_FOLDER_16, IDR_APPS_FOLDER_32, IDR_APPS_FOLDER_OVERLAY_128, IDR_APPS_FOLDER_OVERLAY_512}) { gfx::Image image = resource_bundle.GetNativeImageNamed(id); (*result)[id] = ImageRepForGFXImage(image); } - base::ThreadPool::PostTask( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(std::move(io_task), std::move(result))); + internals::GetShortcutIOTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(std::move(io_task), std::move(result))); } void SetWorkspaceIconOnWorkerThread(const base::FilePath& apps_directory, @@ -778,10 +776,8 @@ if (with_overlay) [folder_icon_image addRepresentation:with_overlay]; } - [NSWorkspace.sharedWorkspace - setIcon:folder_icon_image - forFile:base::apple::FilePathToNSString(apps_directory) - options:0]; + shortcuts::SetIconForFile(folder_icon_image, apps_directory, + base::DoNothing()); } // Adds a localized strings file for the Chrome Apps directory using the current @@ -1593,8 +1589,8 @@ LOG(ERROR) << "Couldn't find an Applications directory to copy app to."; return false; } - // Only set folder icons and a localized name once. This avoids concurrent - // calls to -[NSWorkspace setIcon:..], which is not reentrant. + // Only set folder icons and a localized name once, as nothing should be + // changing the folder icon and name. if (!g_have_localized_app_dir_name) { g_have_localized_app_dir_name = UpdateAppShortcutsSubdirLocalizedName(applications_dir);
diff --git a/chrome/browser/web_applications/web_app_icon_manager.cc b/chrome/browser/web_applications/web_app_icon_manager.cc index 5347292..9f71ebc 100644 --- a/chrome/browser/web_applications/web_app_icon_manager.cc +++ b/chrome/browser/web_applications/web_app_icon_manager.cc
@@ -242,14 +242,14 @@ TRACE_EVENT0("ui", "web_app_icon_manager::ReadIconBlocking"); base::FilePath icon_file = GetIconFileName(web_apps_directory, icon_id); auto icon_data = base::MakeRefCounted<base::RefCountedString>(); - if (!utils->ReadFileToString(icon_file, &icon_data->data())) { + if (!utils->ReadFileToString(icon_file, &icon_data->as_string())) { return {.error_log = {CreateError( {"Could not read icon file: ", icon_file.AsUTF8Unsafe()})}}; } TypedResult<SkBitmap> result; - if (!gfx::PNGCodec::Decode(icon_data->front(), icon_data->size(), + if (!gfx::PNGCodec::Decode(icon_data->data(), icon_data->size(), &result.value)) { return {.error_log = {CreateError({"Could not decode icon data for file: ", icon_file.AsUTF8Unsafe()})}};
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 5aa01597..0d99184 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1713441552-e716922e56c81be3bc716477bf1b016f8c459e53-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-android32-main-1713484561-d78fb7603cf113259fabb5e04edfe8f7c943a6c2-9f1721f07da35be11e0164b09553d85361b8bb28.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index c2846df..8d9e2594 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1713441552-cd143a96ceb690a356d3c5db99b61183c3bcf87d-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-android64-main-1713484561-b637c3dc5684a1fdc510943d46e337d137fdedac-9f1721f07da35be11e0164b09553d85361b8bb28.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt index fc248da..241df633 100644 --- a/chrome/build/lacros-arm64.pgo.txt +++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-arm64-generic-main-1713138865-e4366b1e74fcd8d5a3864edb61cf715e4a651ce4-0e275deada7de65b89c1a83b77086f7a996ae85b.profdata +chrome-chromeos-arm64-generic-main-1713484561-f09c60c5c26ed684f3fbcf7b7da048fe5bd3552d-9f1721f07da35be11e0164b09553d85361b8bb28.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index ab0fff0..90dd29e 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1713441552-d8a9984ff39e53bc77cbb8250e96ade8913b2056-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-chromeos-amd64-generic-main-1713484991-56b3062866b8b52e2b02bb5d6155f2c6cecaf2d9-09eaad15ac8902a8773fac284565ab494d713b02.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index da6bbf03..1eaf5bf 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1713441552-6237be6dcac30c37c8675aa6caeab0d34b34687b-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-linux-main-1713463187-dbf5b9436a1f46a90ee316f44d91d8a67da68350-62be926cd6b6c0421dddfcd23ae9da0781b73344.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 350cfb2..d8d8fdb1 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1713441552-3757d6833d61c0c47e8ec055fca56e2a8c550c97-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-win-arm64-main-1713484561-514756e61e8cc54ae9df5c0b9727ec3f655df2dc-9f1721f07da35be11e0164b09553d85361b8bb28.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index cc2fda0..be10f98 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1713441552-bdee56f7988b5fdcf489fe49e7dc19f7674bc28f-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-win32-main-1713473843-8cfddd58020bd151973dba3c6c371b01e4552635-81fdb072844881cb7a6440bbad3eace782228f05.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index d311088..2408e49 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1713441552-1bfc1cd69dd5a84c8ce8d86b1ded4112b9f74080-9a87fd4ab8453a30bd6b4d00f3b0d0cc6a4c5453.profdata +chrome-win64-main-1713484561-bf1472dce7ecfddb6e36385faaf140130abf1071-9f1721f07da35be11e0164b09553d85361b8bb28.profdata
diff --git a/chrome/common/accessibility/read_anything.mojom b/chrome/common/accessibility/read_anything.mojom index 7b91dc6..dc0d7c1 100644 --- a/chrome/common/accessibility/read_anything.mojom +++ b/chrome/common/accessibility/read_anything.mojom
@@ -162,6 +162,9 @@ // speech via the webui toolbar. lang is the language code that voice is for. OnVoiceChange(string voice, string lang); + // Informs the browser controller that the user enabled/disabled a language. + OnLanguagePrefChange(string lang, bool enabled); + // Informs the browser controller that the user updated the granularity of // the highlight that follows along with speech via the webui toolbar. OnHighlightGranularityChanged(read_anything.mojom.HighlightGranularity granularity); @@ -240,6 +243,7 @@ read_anything.mojom.Colors color, double speech_rate, mojo_base.mojom.DictionaryValue voices, + mojo_base.mojom.ListValue languages_enabled_in_pref, read_anything.mojom.HighlightGranularity granularity); // Notifies the WebUI that the ScreenAI service is ready on this device.
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 84d80b7..dc9fab2 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -235,7 +235,7 @@ BASE_FEATURE(kEnableWatermarkView, "EnableWatermarkView", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #if !BUILDFLAG(IS_ANDROID) // Whether to allow installed-by-default web apps to be installed or not. @@ -397,13 +397,6 @@ "EnableWebUsbOnExtensionServiceWorker", base::FEATURE_ENABLED_BY_DEFAULT); -// When enabled, resource requests on certain pages will be evaluated against -// the Fingerprinting Protection blocklist and possibly blocked via a -// subresource filter. -BASE_FEATURE(kEnableFingerprintingProtectionBlocklist, - "EnableFingerprintingProtectionBlockList", - base::FEATURE_DISABLED_BY_DEFAULT); - #if !BUILDFLAG(IS_ANDROID) // Lazy initialize IndividualSettings for extensions from enterprise policy // that are not installed. @@ -1058,6 +1051,12 @@ base::FEATURE_ENABLED_BY_DEFAULT); #if BUILDFLAG(IS_CHROMEOS) +// Enable the ChromeOS print preview to be opened instead of the browser print +// preview. +BASE_FEATURE(kPrintPreviewCrosPrimary, + "PrintPreviewCrosPrimary", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enable improved printer state and error state messaging for Print Preview. BASE_FEATURE(kPrintPreviewSetupAssistance, "PrintPreviewSetupAssistance",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 8b7781c2..e186d0d 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -233,9 +233,6 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kEnableWebUsbOnExtensionServiceWorker); -COMPONENT_EXPORT(CHROME_FEATURES) -BASE_DECLARE_FEATURE(kEnableFingerprintingProtectionBlocklist); - #if !BUILDFLAG(IS_ANDROID) COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kExtensionDeferredIndividualSettings); @@ -626,6 +623,8 @@ #if BUILDFLAG(IS_CHROMEOS) COMPONENT_EXPORT(CHROME_FEATURES) +BASE_DECLARE_FEATURE(kPrintPreviewCrosPrimary); +COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kPrintPreviewSetupAssistance); COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kLocalPrinterObserving);
diff --git a/chrome/installer/mac/internal b/chrome/installer/mac/internal index 61d6199..41badb0 160000 --- a/chrome/installer/mac/internal +++ b/chrome/installer/mac/internal
@@ -1 +1 @@ -Subproject commit 61d619941db56cde7aaec67bd10e3b4277576404 +Subproject commit 41badb00eefc7b698e126870555c1cb65d1acfdb
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index 68758f09..b360473 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -399,7 +399,13 @@ const std::vector<ui::AXEvent>& events) { // This updates the model, which may require us to start distillation based on // the `requires_distillation()` state below. - model_.AccessibilityEventReceived(tree_id, updates, events); + // + // Remove the const-ness of the data here so that subsequent methods can move + // the data. + model_.AccessibilityEventReceived( + tree_id, const_cast<std::vector<ui::AXTreeUpdate>&>(updates), + const_cast<std::vector<ui::AXEvent>&>(events)); + // From this point onward, `updates` and `events` should not be accessed. if (tree_id != model_.active_tree_id()) { return; @@ -640,11 +646,13 @@ read_anything::mojom::Colors color, double speech_rate, base::Value::Dict voices, + base::Value::List languages_enabled_in_pref, read_anything::mojom::HighlightGranularity granularity) { bool needs_redraw_for_links = model_.links_enabled() != links_enabled; - model_.OnSettingsRestoredFromPrefs(line_spacing, letter_spacing, font, - font_size, links_enabled, color, - speech_rate, &voices, granularity); + model_.OnSettingsRestoredFromPrefs( + line_spacing, letter_spacing, font, font_size, links_enabled, color, + speech_rate, &voices, + &languages_enabled_in_pref, granularity); ExecuteJavaScript("chrome.readingMode.restoreSettingsFromPrefs();"); // Only redraw if there is an active tree. if (needs_redraw_for_links && @@ -747,6 +755,10 @@ &ReadAnythingAppController::OnSpeechRateChange) .SetMethod("getStoredVoice", &ReadAnythingAppController::GetStoredVoice) .SetMethod("onVoiceChange", &ReadAnythingAppController::OnVoiceChange) + .SetMethod("onLanguagePrefChange", + &ReadAnythingAppController::OnLanguagePrefChange) + .SetMethod("getLanguagesEnabledInPref", + &ReadAnythingAppController::GetLanguagesEnabledInPref) .SetMethod("turnedHighlightOn", &ReadAnythingAppController::TurnedHighlightOn) .SetMethod("turnedHighlightOff", @@ -861,6 +873,16 @@ return string_constants::kReadAnythingPlaceholderVoiceName; } +std::vector<std::string> ReadAnythingAppController::GetLanguagesEnabledInPref() + const { + std::vector<std::string> languages_enabled_in_pref; + + for (const base::Value& value : model_.languages_enabled_in_pref()) { + languages_enabled_in_pref.push_back(value.GetString()); + } + return languages_enabled_in_pref; +} + int ReadAnythingAppController::HighlightGranularity() const { return model_.highlight_granularity(); } @@ -1308,6 +1330,11 @@ model_.setVoice(voice, base_lang); } +void ReadAnythingAppController::OnLanguagePrefChange(const std::string& lang, + bool enabled) { + page_handler_->OnLanguagePrefChange(lang, enabled); +} + void ReadAnythingAppController::TurnedHighlightOn() { page_handler_->OnHighlightGranularityChanged( read_anything::mojom::HighlightGranularity::kOn);
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.h b/chrome/renderer/accessibility/read_anything_app_controller.h index 05f8154..6705fb8 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.h +++ b/chrome/renderer/accessibility/read_anything_app_controller.h
@@ -108,6 +108,7 @@ read_anything::mojom::Colors color, double speech_rate, base::Value::Dict voices, + base::Value::List languages_enabled_in_pref, read_anything::mojom::HighlightGranularity granularity) override; void SetLanguageCode(const std::string& code) override; void ScreenAIServiceReady() override; @@ -144,6 +145,7 @@ int YellowTheme() const; int BlueTheme() const; std::string GetStoredVoice() const; + std::vector<std::string> GetLanguagesEnabledInPref() const; std::vector<ui::AXNodeID> GetChildren(ui::AXNodeID ax_node_id) const; std::string GetDataFontCss(ui::AXNodeID ax_node_id) const; std::string GetHtmlTag(ui::AXNodeID ax_node_id) const; @@ -188,6 +190,7 @@ void OnFontChange(const std::string& font); void OnSpeechRateChange(double rate); void OnVoiceChange(const std::string& voice, const std::string& lang); + void OnLanguagePrefChange(const std::string& lang, bool enabled); void TurnedHighlightOn(); void TurnedHighlightOff(); double GetLineSpacingValue(int line_spacing) const;
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index c027b3b..93daeb9 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -80,6 +80,10 @@ (const std::string& voice, const std::string& lang), (override)); MOCK_METHOD(void, + OnLanguagePrefChange, + (const std::string& lang, bool enabled), + (override)); + MOCK_METHOD(void, OnColorChange, (read_anything::mojom::Colors color), (override));
diff --git a/chrome/renderer/accessibility/read_anything_app_model.cc b/chrome/renderer/accessibility/read_anything_app_model.cc index 3915e22..2e6ebeb8 100644 --- a/chrome/renderer/accessibility/read_anything_app_model.cc +++ b/chrome/renderer/accessibility/read_anything_app_model.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/renderer/accessibility/read_anything_app_model.h" + #include <cstddef> #include <string> @@ -85,6 +86,7 @@ read_anything::mojom::Colors color, double speech_rate, base::Value::Dict* voices, + base::Value::List* languages_enabled_in_pref, read_anything::mojom::HighlightGranularity granularity) { line_spacing_ = GetLineSpacingValue(line_spacing); letter_spacing_ = GetLetterSpacingValue(letter_spacing); @@ -94,6 +96,7 @@ color_theme_ = static_cast<size_t>(color); speech_rate_ = speech_rate; voices_ = voices->Clone(); + languages_enabled_in_pref_ = languages_enabled_in_pref->Clone(); highlight_granularity_ = static_cast<size_t>(granularity); } @@ -467,11 +470,11 @@ void ReadAnythingAppModel::AddPendingUpdates( const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates) { - std::vector<ui::AXTreeUpdate> update = GetOrCreatePendingUpdateAt(tree_id); - update.insert(update.end(), std::make_move_iterator(updates.begin()), - std::make_move_iterator(updates.end())); - pending_updates_map_[tree_id] = update; + std::vector<ui::AXTreeUpdate>& updates) { + std::vector<ui::AXTreeUpdate>& update = pending_updates_map_[tree_id]; + for (auto& item : updates) { + update.emplace_back(std::move(item)); + } } void ReadAnythingAppModel::ClearPendingUpdates() { @@ -493,7 +496,7 @@ } void ReadAnythingAppModel::UnserializeUpdates( - const std::vector<ui::AXTreeUpdate>& updates, + std::vector<ui::AXTreeUpdate>& updates, const ui::AXTreeID& tree_id) { if (updates.empty()) { return; @@ -526,8 +529,8 @@ void ReadAnythingAppModel::AccessibilityEventReceived( const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const std::vector<ui::AXEvent>& events) { + std::vector<ui::AXTreeUpdate>& updates, + std::vector<ui::AXEvent>& events) { DCHECK_NE(tree_id, ui::AXTreeIDUnknown()); // Create a new tree if an event is received for a tree that is not yet in // the tree list. @@ -551,10 +554,10 @@ // ones. UnserializePendingUpdates(tree_id); } - UnserializeUpdates(std::move(updates), tree_id); + UnserializeUpdates(updates, tree_id); ProcessNonGeneratedEvents(events); } else { - UnserializeUpdates(std::move(updates), tree_id); + UnserializeUpdates(updates, tree_id); } } @@ -676,15 +679,6 @@ return base::Contains(content_node_ids_, ax_node_id); } -const std::vector<ui::AXTreeUpdate>& -ReadAnythingAppModel::GetOrCreatePendingUpdateAt(const ui::AXTreeID& tree_id) { - if (!pending_updates_map_.contains(tree_id)) { - pending_updates_map_[tree_id] = std::vector<ui::AXTreeUpdate>(); - } - - return pending_updates_map_[tree_id]; -} - double ReadAnythingAppModel::GetLetterSpacingValue( read_anything::mojom::LetterSpacing letter_spacing) const { switch (letter_spacing) { @@ -1167,13 +1161,21 @@ } int ReadAnythingAppModel::GetNextSentence(const std::u16string& text) { - // TODO(crbug.com/40927693): Investigate providing correct line breaks + return GetNextGranularity(text, ax::mojom::TextBoundary::kSentenceStart); +} + +int ReadAnythingAppModel::GetNextWord(const std::u16string& text) { + return GetNextGranularity(text, ax::mojom::TextBoundary::kWordStart); +} + +int ReadAnythingAppModel::GetNextGranularity(const std::u16string& text, + ax::mojom::TextBoundary boundary) { + // TODO(crbug.com/40927698): Investigate providing correct line breaks // or alternatively making adjustments to ax_text_utils to return boundaries // that minimize choppiness. std::vector<int> offsets; - return ui::FindAccessibleTextBoundary(text, offsets, - ax::mojom::TextBoundary::kSentenceStart, - 0, ax::mojom::MoveDirection::kForward, + return ui::FindAccessibleTextBoundary(text, offsets, boundary, 0, + ax::mojom::MoveDirection::kForward, ax::mojom::TextAffinity::kDefaultValue); }
diff --git a/chrome/renderer/accessibility/read_anything_app_model.h b/chrome/renderer/accessibility/read_anything_app_model.h index 65a1441..60066c2a 100644 --- a/chrome/renderer/accessibility/read_anything_app_model.h +++ b/chrome/renderer/accessibility/read_anything_app_model.h
@@ -165,6 +165,9 @@ void setVoice(const std::string& voice, const std::string& lang) { voices_.Set(lang, voice); } + const base::Value::List& languages_enabled_in_pref() const { + return languages_enabled_in_pref_; + } // Selection. bool has_selection() const { return has_selection_; } @@ -231,6 +234,7 @@ read_anything::mojom::Colors color, double speech_rate, base::Value::Dict* voices, + base::Value::List* languages_enabled_in_pref_, read_anything::mojom::HighlightGranularity granularity); void OnScroll(bool on_selection, bool from_reading_mode) const; void OnSelection(ax::mojom::EventFrom event_from); @@ -262,8 +266,8 @@ void ClearPendingUpdates(); void AccessibilityEventReceived(const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates, - const std::vector<ui::AXEvent>& events); + std::vector<ui::AXTreeUpdate>& updates, + std::vector<ui::AXEvent>& events); void OnAXTreeDestroyed(const ui::AXTreeID& tree_id); @@ -293,6 +297,10 @@ // next sentence is equivalent to text.substr(0, <returned_index>). int GetNextSentence(const std::u16string& text); + // Returns the index of the next word of the given text, such that the + // next word is equivalent to text.substr(0, <returned_index>). + int GetNextWord(const std::u16string& text); + // Given a text index for the current granularity, return the AXNodeID for // that part of the text. // For example, if a current granularity segment has text: @@ -368,14 +376,11 @@ bool ContentNodesOnlyContainHeadings(); void AddPendingUpdates(const ui::AXTreeID& tree_id, - const std::vector<ui::AXTreeUpdate>& updates); + std::vector<ui::AXTreeUpdate>& updates); - void UnserializeUpdates(const std::vector<ui::AXTreeUpdate>& updates, + void UnserializeUpdates(std::vector<ui::AXTreeUpdate>& updates, const ui::AXTreeID& tree_id); - const std::vector<ui::AXTreeUpdate>& GetOrCreatePendingUpdateAt( - const ui::AXTreeID& tree_id); - void ProcessNonGeneratedEvents(const std::vector<ui::AXEvent>& events); // The tree size arguments are used to determine if distillation of a PDF is @@ -443,6 +448,11 @@ const ui::AXNodePosition::AXPositionInstance& position, const ui::AXNodePosition::AXPositionInstance& other) const; + // Returns the index of the next granularity of the given text, such that the + // next granularity is equivalent to text.substr(0, <returned_index>). + int GetNextGranularity(const std::u16string& text, + ax::mojom::TextBoundary boundary); + // State. std::map<ui::AXTreeID, std::unique_ptr<ReadAnythingAppModel::AXTreeInfo>> tree_infos_; @@ -502,7 +512,8 @@ SkColor foreground_color_ = (int)read_anything::mojom::Colors::kDefaultValue; int color_theme_ = (int)read_anything::mojom::Colors::kDefaultValue; float speech_rate_ = kReadAnythingDefaultSpeechRate; - base::Value::Dict voices_ = base::Value::Dict(); + base::Value::Dict voices_; + base::Value::List languages_enabled_in_pref_; int highlight_granularity_ = (int)read_anything::mojom::HighlightGranularity::kDefaultValue;
diff --git a/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc index 5689530..451952b 100644 --- a/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_model_browsertest.cc
@@ -104,7 +104,9 @@ void AccessibilityEventReceived( const ui::AXTreeID& tree_id, const std::vector<ui::AXTreeUpdate>& updates) { - model_->AccessibilityEventReceived(tree_id, updates, {}); + std::vector<ui::AXEvent> events; + model_->AccessibilityEventReceived( + tree_id, const_cast<std::vector<ui::AXTreeUpdate>&>(updates), events); } void set_active_tree_id(ui::AXTreeID tree_id) { @@ -244,6 +246,10 @@ return model_->GetNextSentence(text); } + size_t GetNextWord(const std::u16string& text) { + return model_->GetNextWord(text); + } + ui::AXNodeID GetNodeIdForCurrentSegmentIndex(int index) { ui::AXNodeID id = model_->GetNodeIdForCurrentSegmentIndex(index); return id; @@ -1560,6 +1566,25 @@ EXPECT_EQ(sentence.substr(0, index), sentence); } +TEST_F(ReadAnythingAppModelTest, GetNextWord_ReturnsCorrectIndex) { + const std::u16string first_word = u"onomatopoeia "; + const std::u16string second_word = u"party"; + + const std::u16string segment = first_word + second_word; + size_t index = GetNextWord(segment); + EXPECT_EQ(index, first_word.length()); + EXPECT_EQ(segment.substr(0, index), first_word); +} + +TEST_F(ReadAnythingAppModelTest, + GetNextWord_OnlyOneWord_ReturnsCorrectIndex) { + const std::u16string word = u"Happiness"; + + size_t index = GetNextWord(word); + EXPECT_EQ(index, word.length()); + EXPECT_EQ(word.substr(0, index), word); +} + TEST_F(ReadAnythingAppModelTest, GetNextValidPosition) { std::u16string sentence1 = u"This is a sentence."; std::u16string sentence2 = u"This is another sentence.";
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 49b6557..79fa37ee 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -339,8 +339,8 @@ std::vector<FormFieldData> fields; for (size_t i = 0; i < labels.size(); ++i) { FormFieldData expected; - expected.id_attribute = id_attributes[i]; - expected.name_attribute = name_attributes[i]; + expected.set_id_attribute(id_attributes[i]); + expected.set_name_attribute(name_attributes[i]); expected.set_label(labels[i]); expected.set_name(names[i]); expected.set_value(values[i]); @@ -475,8 +475,8 @@ expected.form_control_type() == FormControlType::kTextArea) ? FormFieldData::kDefaultMaxLength : 0; - expected.id_attribute = ASCIIToUTF16(field_cases[i].id_attribute); - expected.set_name(expected.id_attribute); + expected.set_id_attribute(ASCIIToUTF16(field_cases[i].id_attribute)); + expected.set_name(expected.id_attribute()); expected.set_value(ASCIIToUTF16(field_cases[i].initial_value)); if (expected.form_control_type() == FormControlType::kInputText || expected.form_control_type() == FormControlType::kInputMonth) { @@ -708,29 +708,29 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); EXPECT_FORM_FIELD_DATA_EQUALS(expected, field); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_label(u"john@example.com"); expected.autocomplete_attribute = "off"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.autocomplete_attribute = {}; - expected.id_attribute = u"phone"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"phone"); + expected.set_name(expected.id_attribute()); expected.set_value(u"1.800.555.1234"); expected.set_label(u"1.800.555.1234"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); @@ -765,24 +765,24 @@ FormFieldData expected; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_label(u"john@example.com"); expected.autocomplete_attribute = "off"; @@ -791,8 +791,8 @@ EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.autocomplete_attribute = {}; - expected.id_attribute = u"street-address"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"street-address"); + expected.set_name(expected.id_attribute()); expected.set_value(u"123 Fantasy Ln.\nApt. 42"); expected.set_label({}); expected.set_form_control_type(FormControlType::kTextArea); @@ -828,20 +828,20 @@ FormFieldData expected; expected.set_form_control_type(FormControlType::kInputText); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.max_length = 5; expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.max_length = 7; expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.max_length = 9; expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); @@ -871,22 +871,22 @@ expected.set_form_control_type(FormControlType::kInputText); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Broth"); expected.max_length = 5; expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Jonatha"); expected.max_length = 7; expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"brotherj@"); expected.max_length = 9; expected.is_autofilled = true; @@ -921,16 +921,16 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); // Fill the form. @@ -953,18 +953,18 @@ const std::vector<FormFieldData>& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Brother"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Jonathan"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"brotherj@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } @@ -997,16 +997,16 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); // Fill the form. @@ -1032,18 +1032,18 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Wyatt"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Earp"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"wyatt@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); } @@ -1078,18 +1078,18 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"apple"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"apple"); + expected.set_name(expected.id_attribute()); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset]); - expected.id_attribute = u"banana"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"banana"); + expected.set_name(expected.id_attribute()); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset + 1]); - expected.id_attribute = u"cantelope"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"cantelope"); + expected.set_name(expected.id_attribute()); expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[unowned_offset + 2]); @@ -1116,20 +1116,20 @@ const std::vector<FormFieldData>& fields2 = form2.fields; ASSERT_EQ(unowned_offset + 3, fields2.size()); - expected.id_attribute = u"apple"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"apple"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Red"); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 0]); - expected.id_attribute = u"banana"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"banana"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Yellow"); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 1]); - expected.id_attribute = u"cantelope"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"cantelope"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Also Yellow"); expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[unowned_offset + 2]); @@ -1172,8 +1172,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Wy"); if (placeholder_firstname) { expected.set_label(ASCIIToUTF16(placeholder_firstname)); @@ -1182,8 +1182,8 @@ expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); if (initial_lastname) { expected.set_label(ASCIIToUTF16(initial_lastname)); expected.set_value(ASCIIToUTF16(initial_lastname)); @@ -1198,8 +1198,8 @@ expected.is_autofilled = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); if (initial_email) { expected.set_label(ASCIIToUTF16(initial_email)); expected.set_value(ASCIIToUTF16(initial_email)); @@ -1244,8 +1244,8 @@ const std::vector<FormFieldData>& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Wyatt"); if (placeholder_firstname) { expected.set_label(ASCIIToUTF16(placeholder_firstname)); @@ -1257,8 +1257,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Earp"); if (placeholder_lastname) { expected.set_label(ASCIIToUTF16(placeholder_lastname)); @@ -1270,8 +1270,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"wyatt@example.com"); if (placeholder_email) { expected.set_label(ASCIIToUTF16(placeholder_email)); @@ -1391,8 +1391,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Wyatt"); if (placeholder_firstname) { expected.set_label(ASCIIToUTF16(placeholder_firstname)); @@ -1406,8 +1406,8 @@ EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); // The last name field is not filled, because there is a value in it. - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Earp"); if (placeholder_lastname) { expected.set_label(ASCIIToUTF16(placeholder_lastname)); @@ -1420,8 +1420,8 @@ expected.is_user_edited = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"phone"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"phone"); + expected.set_name(expected.id_attribute()); expected.set_value(u"888-123-4567"); if (placeholder_phone) { expected.set_label(ASCIIToUTF16(placeholder_phone)); @@ -1434,8 +1434,8 @@ expected.is_user_edited = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); - expected.id_attribute = u"cc"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"cc"); + expected.set_name(expected.id_attribute()); expected.set_value(u"1111-2222-3333-4444"); if (placeholder_creditcard) { expected.set_label(ASCIIToUTF16(placeholder_creditcard)); @@ -1448,8 +1448,8 @@ expected.is_user_edited = false; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[3]); - expected.id_attribute = u"city"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"city"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Montreal"); if (placeholder_city) { expected.set_label(ASCIIToUTF16(placeholder_city)); @@ -1463,9 +1463,9 @@ EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[4]); expected.set_form_control_type(FormControlType::kSelectOne); - expected.id_attribute = u"state"; - expected.name_attribute = u"state"; - expected.set_name(expected.name_attribute); + expected.set_id_attribute(u"state"); + expected.set_name_attribute(u"state"); + expected.set_name(expected.name_attribute()); expected.set_value(u"AA"); if (placeholder_state) { expected.set_label(ASCIIToUTF16(placeholder_state)); @@ -1550,8 +1550,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Wyatt"); if (placeholder_firstname) { expected.set_label(ASCIIToUTF16(placeholder_firstname)); @@ -1563,8 +1563,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Earpagus"); if (placeholder_lastname) { expected.set_label(ASCIIToUTF16(placeholder_lastname)); @@ -1577,8 +1577,8 @@ EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); // The email field is not filled, because there is a value in it. - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@smith.com"); if (placeholder_email) { expected.set_label(ASCIIToUTF16(placeholder_email)); @@ -1664,8 +1664,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"cc"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"cc"); + expected.set_name(expected.id_attribute()); expected.set_value(u"1111-2222-3333-4444"); if (placeholder_creditcard) { expected.set_label(ASCIIToUTF16(placeholder_creditcard)); @@ -1677,8 +1677,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"expiration_date"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"expiration_date"); + expected.set_name(expected.id_attribute()); expected.set_value(u"03/2030"); if (placeholder_expiration) { expected.set_label(ASCIIToUTF16(placeholder_expiration)); @@ -1690,8 +1690,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"name"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"name"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John Smith"); if (placeholder_name) { expected.set_label(ASCIIToUTF16(placeholder_name)); @@ -1786,8 +1786,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"cc"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"cc"); + expected.set_name(expected.id_attribute()); expected.set_value(u"1111-2222-3333-4444"); if (placeholder_creditcard) { expected.set_label(ASCIIToUTF16(placeholder_creditcard)); @@ -1799,8 +1799,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"expiration_date"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"expiration_date"); + expected.set_name(expected.id_attribute()); expected.set_value(u"03/2030"); if (placeholder_expiration) { expected.set_label(ASCIIToUTF16(placeholder_expiration)); @@ -1812,8 +1812,8 @@ expected.is_autofilled = true; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"name"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"name"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John Smith"); if (placeholder_name) { expected.set_label(ASCIIToUTF16(placeholder_name)); @@ -1878,59 +1878,59 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"noAC"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"noAC"); + expected.set_name(expected.id_attribute()); expected.set_value(u"one"); expected.set_label(u"one"); expected.autocomplete_attribute = "off"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.autocomplete_attribute = {}; - expected.id_attribute = u"notenabled"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"notenabled"); + expected.set_name(expected.id_attribute()); expected.set_value(u"no clear"); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); expected.set_form_control_type(FormControlType::kInputMonth); expected.max_length = 0; - expected.id_attribute = u"month"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"month"); + expected.set_name(expected.id_attribute()); expected.set_value({}); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); - expected.id_attribute = u"month-disabled"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"month-disabled"); + expected.set_name(expected.id_attribute()); expected.set_value(u"2012-11"); expected.set_label(u"2012-11"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); expected.set_form_control_type(FormControlType::kTextArea); - expected.id_attribute = u"textarea"; + expected.set_id_attribute(u"textarea"); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value({}); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[6]); - expected.id_attribute = u"textarea-disabled"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"textarea-disabled"); + expected.set_name(expected.id_attribute()); expected.set_value(u" Banana!\n "); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[7]); - expected.id_attribute = u"textarea-noAC"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"textarea-noAC"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Carrot?"); expected.autocomplete_attribute = "off"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[8]); @@ -2016,32 +2016,32 @@ // shipping section expected.is_autofilled = false; - expected.id_attribute = u"firstname-shipping"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname-shipping"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname-shipping"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname-shipping"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"city-shipping"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"city-shipping"); + expected.set_name(expected.id_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); // billing section expected.is_autofilled = true; - expected.id_attribute = u"firstname-billing"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname-billing"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); - expected.id_attribute = u"lastname-billing"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname-billing"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); - expected.id_attribute = u"city-billing"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"city-billing"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Paris"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); @@ -2094,23 +2094,23 @@ FormFieldData expected; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value({}); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value({}); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"state"; - expected.name_attribute = u"state"; - expected.set_name(expected.name_attribute); + expected.set_id_attribute(u"state"); + expected.set_name_attribute(u"state"); + expected.set_name(expected.name_attribute()); expected.set_value(u"?"); expected.set_form_control_type(FormControlType::kSelectOne); expected.max_length = 0; @@ -2375,8 +2375,8 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.set_value({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result1); @@ -2402,8 +2402,8 @@ {ExtractOption::kValue}, &result); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.set_value(u"value"); expected.set_form_control_type(FormControlType::kInputText); expected.autocomplete_attribute = "off"; @@ -2424,8 +2424,8 @@ {ExtractOption::kValue}, &result); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.set_value(u"value"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = 5; @@ -2446,8 +2446,8 @@ {ExtractOption::kValue}, &result); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.set_value(u"value"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; @@ -2471,8 +2471,8 @@ {ExtractOption::kValue}, &result); FormFieldData expected; - expected.id_attribute = u"checkbox"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"checkbox"); + expected.set_name(expected.id_attribute()); expected.set_value(u"mail"); expected.set_form_control_type(FormControlType::kInputCheckbox); expected.max_length = 0; @@ -2484,8 +2484,8 @@ element.SetAutofillState(WebAutofillState::kAutofilled); WebFormControlElementToFormField(WebFormElement(), element, nullptr, {ExtractOption::kValue}, &result); - expected.id_attribute = u"radio"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"radio"); + expected.set_name(expected.id_attribute()); expected.set_value(u"male"); expected.set_form_control_type(FormControlType::kInputRadio); expected.max_length = 0; @@ -2510,8 +2510,8 @@ {ExtractOption::kValue}, &result1); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.max_length = 0; expected.set_form_control_type(FormControlType::kSelectOne); @@ -2557,8 +2557,8 @@ {ExtractOption::kValue}, &result1); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.max_length = 0; expected.set_form_control_type(FormControlType::kSelectOne); // We check that the extra attributes have been copied to `result1`. @@ -2651,8 +2651,8 @@ /*extract_options=*/{}, &result_sans_value); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.max_length = FormFieldData::kDefaultMaxLength; expected.set_form_control_type(FormControlType::kTextArea); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); @@ -2679,8 +2679,8 @@ /*extract_options=*/{}, &result_sans_value); FormFieldData expected; - expected.id_attribute = u"element"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"element"); + expected.set_name(expected.id_attribute()); expected.max_length = 0; expected.set_form_control_type(FormControlType::kInputMonth); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result_sans_value); @@ -2708,8 +2708,8 @@ FormFieldData expected; expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"password"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"password"); + expected.set_name(expected.id_attribute()); expected.set_form_control_type(FormControlType::kInputPassword); expected.set_value(u"secret"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); @@ -2781,8 +2781,8 @@ /*extract_options=*/{}, &result); FormFieldData expected; - expected.id_attribute = ASCIIToUTF16(test_case.element_id); - expected.set_name(expected.id_attribute); + expected.set_id_attribute(ASCIIToUTF16(test_case.element_id)); + expected.set_name(expected.id_attribute()); expected.set_form_control_type(test_case.form_control_type); expected.max_length = (test_case.form_control_type == FormControlType::kInputText || @@ -2987,48 +2987,48 @@ ASSERT_EQ(6U, fields.size()); FormFieldData expected; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"First name:"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Last name:"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"street-address"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"street-address"); + expected.set_name(expected.id_attribute()); expected.set_value(u"123 Fantasy Ln.\nApt. 42"); expected.set_label(u"Address:"); expected.set_form_control_type(FormControlType::kTextArea); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); - expected.id_attribute = u"state"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"state"); + expected.set_name(expected.id_attribute()); expected.set_value(u"CA"); expected.set_label(u"State:"); expected.set_form_control_type(FormControlType::kSelectOne); expected.max_length = 0; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); - expected.id_attribute = u"password"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"password"); + expected.set_name(expected.id_attribute()); expected.set_value(u"secret"); expected.set_label(u"Password:"); expected.set_form_control_type(FormControlType::kInputPassword); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); - expected.id_attribute = u"month"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"month"); + expected.set_name(expected.id_attribute()); expected.set_value(u"2011-12"); expected.set_label(u"Card expiration:"); expected.set_form_control_type(FormControlType::kInputMonth); @@ -3223,16 +3223,16 @@ EXPECT_EQ(4U, form.fields.size()); // id attributes. - EXPECT_EQ(u"firstname", form.fields[0].id_attribute); - EXPECT_EQ(u"lastname", form.fields[1].id_attribute); - EXPECT_EQ(u"same", form.fields[2].id_attribute); - EXPECT_EQ(u"addressline1", form.fields[3].id_attribute); + EXPECT_EQ(u"firstname", form.fields[0].id_attribute()); + EXPECT_EQ(u"lastname", form.fields[1].id_attribute()); + EXPECT_EQ(u"same", form.fields[2].id_attribute()); + EXPECT_EQ(u"addressline1", form.fields[3].id_attribute()); // name attributes. - EXPECT_EQ(u"name1", form.fields[0].name_attribute); - EXPECT_EQ(u"name2", form.fields[1].name_attribute); - EXPECT_EQ(u"same", form.fields[2].name_attribute); - EXPECT_EQ(u"", form.fields[3].name_attribute); + EXPECT_EQ(u"name1", form.fields[0].name_attribute()); + EXPECT_EQ(u"name2", form.fields[1].name_attribute()); + EXPECT_EQ(u"same", form.fields[2].name_attribute()); + EXPECT_EQ(u"", form.fields[3].name_attribute()); // name for autofill EXPECT_EQ(u"name1", form.fields[0].name()); @@ -3284,20 +3284,20 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_label(u"john@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); @@ -3310,20 +3310,20 @@ const std::vector<FormFieldData>& fields2 = form2.fields; ASSERT_EQ(3U, fields2.size()); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Jack"); expected.set_label(u"Jack"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Adams"); expected.set_label(u"Adams"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"jack@example.com"); expected.set_label(u"jack@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); @@ -3368,26 +3368,26 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_label(u"john@example.com"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); - expected.id_attribute = u"telephone"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"telephone"); + expected.set_name(expected.id_attribute()); expected.set_value(u"12345"); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); @@ -3425,20 +3425,20 @@ const std::vector<FormFieldData>& fields2 = forms[0].fields; ASSERT_EQ(3U, fields2.size()); - expected.id_attribute = u"second_firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"second_firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Bob"); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]); - expected.id_attribute = u"second_lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"second_lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Hope"); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]); - expected.id_attribute = u"second_email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"second_email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"bobhope@example.com"); expected.set_label({}); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]); @@ -3997,46 +3997,46 @@ FormFieldData expected; std::vector<FormFieldData> fields; - expected.id_attribute = u"firstname"; - expected.name_attribute = u""; + expected.set_id_attribute(u"firstname"); + expected.set_name_attribute(u""); expected.set_label(u"* First Name"); - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; fields.push_back(expected); - expected.id_attribute = u"middlename"; - expected.name_attribute = u""; + expected.set_id_attribute(u"middlename"); + expected.set_name_attribute(u""); expected.set_label(u"* Middle Name"); - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value(u"Joe"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; fields.push_back(expected); - expected.id_attribute = u"lastname"; - expected.name_attribute = u""; + expected.set_id_attribute(u"lastname"); + expected.set_name_attribute(u""); expected.set_label(u"* Last Name"); - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; fields.push_back(expected); - expected.id_attribute = u"country"; - expected.name_attribute = u""; + expected.set_id_attribute(u"country"); + expected.set_name_attribute(u""); expected.set_label(u"* Country"); - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value(u"US"); expected.set_form_control_type(FormControlType::kSelectOne); expected.max_length = 0; fields.push_back(expected); - expected.id_attribute = u"email"; - expected.name_attribute = u""; + expected.set_id_attribute(u"email"); + expected.set_name_attribute(u""); expected.set_label(u"* Email"); - expected.set_name(expected.id_attribute); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; @@ -4798,23 +4798,23 @@ expected.max_length = FormFieldData::kDefaultMaxLength; expected.set_label(u"Phone:"); - expected.name_attribute = u"dayphone1"; - expected.set_name(expected.name_attribute); + expected.set_name_attribute(u"dayphone1"); + expected.set_name(expected.name_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); expected.set_label(u""); - expected.name_attribute = u"dayphone2"; - expected.set_name(expected.name_attribute); + expected.set_name_attribute(u"dayphone2"); + expected.set_name(expected.name_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); expected.set_label(u""); - expected.name_attribute = u"dayphone3"; - expected.set_name(expected.name_attribute); + expected.set_name_attribute(u"dayphone3"); + expected.set_name(expected.name_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); expected.set_label(u"ext.:"); - expected.name_attribute = u"dayphone4"; - expected.set_name(expected.name_attribute); + expected.set_name_attribute(u"dayphone4"); + expected.set_name(expected.name_attribute()); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); } @@ -4851,41 +4851,41 @@ FormFieldData expected; expected.set_form_control_type(FormControlType::kInputText); - expected.name_attribute = u"dayphone1"; + expected.set_name_attribute(u"dayphone1"); expected.set_label(u"Phone:"); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = 3; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.name_attribute = u"dayphone2"; + expected.set_name_attribute(u"dayphone2"); expected.set_label(u""); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = 3; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.name_attribute = u"dayphone3"; + expected.set_name_attribute(u"dayphone3"); expected.set_label(u""); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = 4; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]); - expected.name_attribute = u"dayphone4"; + expected.set_name_attribute(u"dayphone4"); expected.set_label(u"ext.:"); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = 5; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]); // When unspecified `size`, default is returned. - expected.name_attribute = u"default1"; + expected.set_name_attribute(u"default1"); expected.set_label({}); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[4]); // When invalid `size`, default is returned. - expected.name_attribute = u"invalid1"; + expected.set_name_attribute(u"invalid1"); expected.set_label({}); - expected.set_name(expected.name_attribute); + expected.set_name(expected.name_attribute()); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[5]); } @@ -5382,24 +5382,24 @@ FormFieldData expected; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"country"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"country"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Albania"); expected.set_label({}); expected.set_form_control_type(FormControlType::kSelectOne); @@ -5416,24 +5416,24 @@ ASSERT_EQ(3U, fields.size()); - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"John"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Smith"); expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"country"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"country"); + expected.set_name(expected.id_attribute()); expected.set_value(u"AL"); expected.set_label({}); expected.set_form_control_type(FormControlType::kSelectOne); @@ -5465,20 +5465,20 @@ expected.set_form_control_type(FormControlType::kInputText); expected.max_length = FormFieldData::kDefaultMaxLength; - expected.id_attribute = u"firstname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"firstname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"John"); expected.set_label(u"First name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]); - expected.id_attribute = u"lastname"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"lastname"); + expected.set_name(expected.id_attribute()); expected.set_value(u"Smith"); expected.set_label(u"Last name:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]); - expected.id_attribute = u"email"; - expected.set_name(expected.id_attribute); + expected.set_id_attribute(u"email"); + expected.set_name(expected.id_attribute()); expected.set_value(u"john@example.com"); expected.set_label(u"Email:"); EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]);
diff --git a/chrome/services/sharing/nearby/BUILD.gn b/chrome/services/sharing/nearby/BUILD.gn index 62759749..8bcbeb4a 100644 --- a/chrome/services/sharing/nearby/BUILD.gn +++ b/chrome/services/sharing/nearby/BUILD.gn
@@ -14,8 +14,6 @@ "nearby_connections_stream_buffer_manager.h", "nearby_presence.cc", "nearby_presence.h", - "nearby_presence_conversions.cc", - "nearby_presence_conversions.h", "nearby_shared_remotes.cc", "nearby_shared_remotes.h", "platform.cc", @@ -40,6 +38,7 @@ deps = [ "//chrome/browser/nearby_sharing/logging", + "//chromeos/ash/components/nearby/presence/conversions:conversions", "//chromeos/services/network_config/public/mojom", "//components/cross_device/nearby:nearby", ] @@ -59,6 +58,7 @@ "test_support", "//ash/public/cpp", "//base/test:test_support", + "//chromeos/ash/components/nearby/presence/conversions:conversions", "//chromeos/ash/services/nearby/public/cpp:test_support", "//chromeos/ash/services/network_config/public/cpp:test_support", "//testing/gmock",
diff --git a/chrome/services/sharing/nearby/DEPS b/chrome/services/sharing/nearby/DEPS index 9f05ad4..716d9ef 100644 --- a/chrome/services/sharing/nearby/DEPS +++ b/chrome/services/sharing/nearby/DEPS
@@ -3,7 +3,22 @@ # found in the LICENSE file. include_rules = [ + # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for + # details. + "-chrome", + + # This directory is in //chrome, which violates the rule above. Allow this + # directory to #include its own files. + "+chrome/services/sharing/nearby", + + # Existing dependencies within //chrome. Whenever possible, avoid adding new + # //chrome dependencies to this list. Dependencies within //chrome are listed + # on a per- directory basis. See //tools/chromeos/gen_deps.sh for details. + "+chrome/services/sharing/public/cpp", + "+chrome/services/sharing/public/proto", + "+chrome/services/sharing/webrtc", "+chrome/browser/nearby_sharing/logging", + "+chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h", "+components/cross_device/logging", "+components/cross_device/nearby/nearby_features.h", "+third_party/nearby",
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc index 1f2fe09b..7c4e910 100644 --- a/chrome/services/sharing/nearby/nearby_connections.cc +++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -14,8 +14,8 @@ #include "base/time/time.h" #include "chrome/browser/nearby_sharing/logging/logging.h" #include "chrome/services/sharing/nearby/nearby_connections_conversions.h" -#include "chrome/services/sharing/nearby/nearby_presence_conversions.h" #include "chrome/services/sharing/nearby/platform/input_file.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "chromeos/ash/services/nearby/public/mojom/webrtc.mojom.h" #include "components/cross_device/logging/logging.h"
diff --git a/chrome/services/sharing/nearby/nearby_connections_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_unittest.cc index 3a98a7f..b68dbeb51 100644 --- a/chrome/services/sharing/nearby/nearby_connections_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/services/sharing/nearby/nearby_connections.h" #include <stdint.h> + #include <sstream> #include "ash/public/cpp/network_config_service.h" @@ -19,9 +20,9 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "chrome/services/sharing/nearby/nearby_connections_conversions.h" -#include "chrome/services/sharing/nearby/nearby_presence_conversions.h" #include "chrome/services/sharing/nearby/test_support/fake_adapter.h" #include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "chromeos/ash/services/nearby/public/cpp/fake_firewall_hole_factory.h" #include "chromeos/ash/services/nearby/public/cpp/fake_tcp_socket_factory.h" #include "chromeos/ash/services/nearby/public/mojom/firewall_hole.mojom.h"
diff --git a/chrome/services/sharing/nearby/nearby_presence.cc b/chrome/services/sharing/nearby/nearby_presence.cc index c46540c2..564c01e 100644 --- a/chrome/services/sharing/nearby/nearby_presence.cc +++ b/chrome/services/sharing/nearby/nearby_presence.cc
@@ -3,9 +3,10 @@ // found in the LICENSE file. #include "chrome/services/sharing/nearby/nearby_presence.h" + #include "base/strings/string_number_conversions.h" -#include "chrome/services/sharing/nearby/nearby_presence_conversions.h" #include "chrome/services/sharing/nearby/nearby_shared_remotes.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "components/cross_device/logging/logging.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/abseil-cpp/absl/status/status.h"
diff --git a/chrome/services/sharing/nearby/nearby_presence_unittest.cc b/chrome/services/sharing/nearby/nearby_presence_unittest.cc index f2f6a84..896a63c6 100644 --- a/chrome/services/sharing/nearby/nearby_presence_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_presence_unittest.cc
@@ -9,6 +9,7 @@ #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/task_environment.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h"
diff --git a/chrome/services/sharing/nearby/platform/BUILD.gn b/chrome/services/sharing/nearby/platform/BUILD.gn index 3f24fb1..6f30b09 100644 --- a/chrome/services/sharing/nearby/platform/BUILD.gn +++ b/chrome/services/sharing/nearby/platform/BUILD.gn
@@ -44,7 +44,6 @@ "count_down_latch.h", "credential_storage.cc", "credential_storage.h", - "crypto.cc", "input_file.cc", "input_file.h", "input_stream_impl.cc", @@ -63,7 +62,6 @@ "scheduled_executor.h", "submittable_executor.cc", "submittable_executor.h", - "system_clock.cc", "webrtc.cc", "webrtc.h", "wifi_lan_medium.cc", @@ -86,8 +84,8 @@ deps = [ "//ash/constants", "//base", + "//chrome/browser/nearby_sharing/common", "//chrome/services/sharing/webrtc", - "//chromeos/ash/components/nearby/common/connections_manager:connections_manager", "//chromeos/ash/components/nearby/presence/conversions:conversions", "//chromeos/ash/services/nearby/public/cpp:tcp_server_socket_port", "//chromeos/ash/services/nearby/public/mojom", @@ -126,7 +124,6 @@ "condition_variable_unittest.cc", "count_down_latch_unittest.cc", "credential_storage_unittest.cc", - "crypto_unittest.cc", "input_file_unittest.cc", "input_stream_impl_unittest.cc", "multi_thread_executor_unittest.cc", @@ -144,6 +141,7 @@ deps = [ ":platform", "//base/test:test_support", + "//chrome/browser/nearby_sharing/common:common", "//chrome/services/sharing/nearby/test_support", "//chromeos/ash/components/login/login_state", "//chromeos/ash/components/nearby/common/connections_manager:connections_manager",
diff --git a/chrome/services/sharing/nearby/platform/DEPS b/chrome/services/sharing/nearby/platform/DEPS index 52e3bee..65bb3c61 100644 --- a/chrome/services/sharing/nearby/platform/DEPS +++ b/chrome/services/sharing/nearby/platform/DEPS
@@ -3,6 +3,10 @@ # found in the LICENSE file. include_rules = [ + # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for + # details. + '-chrome', + '+ash/constants/ash_features.h', '+device/bluetooth', '+services/network/public', @@ -10,6 +14,15 @@ '+third_party/abseil-cpp/absl/time/time.h', '+third_party/nearby', '+unicode/locid.h', + + # Existing dependencies within //chrome. Whenever possible, avoid adding new + # //chrome dependencies to this list. Dependencies within //chrome are listed + # on a per- directory basis. See //tools/chromeos/gen_deps.sh for details. + '+chrome/browser/nearby_sharing/common/nearby_share_features.h', + '+chrome/services/sharing/nearby/platform', + '+chrome/services/sharing/nearby/test_support', + '+chrome/services/sharing/webrtc', + '+chromeos/ash/components/login/login_state/login_state.h', '+chromeos/ash/components/network/proxy/ui_proxy_config_service.h', '+chromeos/ash/components/network/managed_network_configuration_handler.h',
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 98b6e6bc..fcb11e89 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -848,6 +848,7 @@ "//ash:test_support", "//ash/constants", "//ash/public/cpp:test_support", + "//ash/webui/diagnostics_ui:url_constants", "//ash/webui/firmware_update_ui:url_constants", "//ash/webui/os_feedback_ui:url_constants", "//ash/webui/personalization_app:test_support", @@ -1331,6 +1332,7 @@ "../browser/accessibility/accessibility_prefs/android/accessibility_android_policy_browsertest.cc", "../browser/accessibility/accessibility_prefs/android/accessibility_prefs_controller_browsertest.cc", "../browser/android/auxiliary_search/auxiliary_search_provider_browsertest.cc", + "../browser/android/cookies/cookies_fetcher_restore_util_browsertest.cc", "../browser/android/customtabs/custom_tabs_browsertest.cc", "../browser/android/customtabs/tab_interaction_recorder_browsertest.cc", "../browser/android/historical_tab_saver_browsertest.cc", @@ -1842,6 +1844,7 @@ "//components/feature_engagement/test:test_support", "//components/feedback:feedback", "//components/feedback/redaction_tool", + "//components/fingerprinting_protection_filter/browser", "//components/flags_ui", "//components/heavy_ad_intervention", "//components/history/content/browser", @@ -7065,6 +7068,7 @@ "//components/tab_groups", "//components/tpcd/metadata", "//components/tpcd/metadata:metadata_proto", + "//components/tpcd/metadata:prefs", "//components/tpcd/metadata:test_support", "//components/tracing:background_tracing_utils", "//components/tracing:startup_tracing", @@ -8545,7 +8549,6 @@ "../browser/nearby_sharing/mock_nearby_sharing_service.cc", "../browser/nearby_sharing/mock_nearby_sharing_service.h", "../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc", - "../browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc", "../browser/nearby_sharing/nearby_notification_manager_unittest.cc", "../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc", "../browser/nearby_sharing/nearby_receive_manager_unittest.cc", @@ -9351,6 +9354,7 @@ deps += [ "//chrome/browser/extensions:cws_item_service_proto", "//chrome/browser/extensions:test_support", + "//chrome/browser/shortcuts:unit_tests", "//chrome/browser/ui/web_applications:unit_tests", "//chrome/browser/web_applications:unit_tests", "//chrome/browser/web_applications:web_applications_unit_tests",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS index 129ba197..7e64b338 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS
@@ -31,6 +31,7 @@ "+components/favicon/core", "+components/feature_engagement", "+components/find_in_page", + "+components/fingerprinting_protection_filter/browser", "+components/gcm_driver/instance_id", "+components/global_media_controls", "+components/google/core/common",
diff --git a/chrome/test/data/password/captured_sites/artifacts b/chrome/test/data/password/captured_sites/artifacts index d8bb2ef..9c7a49b 160000 --- a/chrome/test/data/password/captured_sites/artifacts +++ b/chrome/test/data/password/captured_sites/artifacts
@@ -1 +1 @@ -Subproject commit d8bb2ef5c0ebff18c66f02e534a3f20bef7d55f5 +Subproject commit 9c7a49bc3fe9540bc90520a74a77b5f99c3664a9
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index f729930..722ff76 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -103,6 +103,7 @@ "chromeos/ash_common/cr_elements/ash_common_cr_elements_browsertest.cc", "chromeos/ash_common/sea_pen/sea_pen_browsertest.cc", "chromeos/ash_common/webui_resource_browsertest.cc", + "chromeos/diagnostics/diagnostics_browsertest.cc", "chromeos/edu_coexistence/edu_coexistence_browsertest.cc", "chromeos/enterprise_reporting/enterprise_reporting_browsertest.cc", "chromeos/extended_updates/extended_updates_browsertest.cc", @@ -504,6 +505,7 @@ "chromeos:build_web_ui_test_mojo_lite_grdp", "chromeos/ash_common:build_grdp", "chromeos/ash_common/cr_elements:build_grdp", + "chromeos/ash_common/sea_pen:build_grdp", "chromeos/borealis_installer:build_grdp", "chromeos/cloud_upload:build_grdp", "chromeos/diagnostics:build_grdp", @@ -534,6 +536,7 @@ grdp_files += [ "$target_gen_dir/chromeos/ash_common/resources.grdp", "$target_gen_dir/chromeos/ash_common/cr_elements/resources.grdp", + "$target_gen_dir/chromeos/ash_common/sea_pen/resources.grdp", "$target_gen_dir/chromeos/borealis_installer/resources.grdp", "$target_gen_dir/chromeos/cloud_upload/resources.grdp", "$target_gen_dir/chromeos/diagnostics/resources.grdp",
diff --git a/chrome/test/data/webui/chromeos/BUILD.gn b/chrome/test/data/webui/chromeos/BUILD.gn index fdb829e..c4ef02e4 100644 --- a/chrome/test/data/webui/chromeos/BUILD.gn +++ b/chrome/test/data/webui/chromeos/BUILD.gn
@@ -92,7 +92,6 @@ sources = [ "../nearby_share/nearby_browsertest.js", "../nearby_share/shared/nearby_shared_v3_browsertest.js", - "diagnostics/diagnostics_browsertest.js", "manage_mirrorsync/manage_mirrorsync_browsertest.js", ] defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
diff --git a/chrome/test/data/webui/chromeos/ash_common/BUILD.gn b/chrome/test/data/webui/chromeos/ash_common/BUILD.gn index 7985824..bff13c367 100644 --- a/chrome/test/data/webui/chromeos/ash_common/BUILD.gn +++ b/chrome/test/data/webui/chromeos/ash_common/BUILD.gn
@@ -31,15 +31,12 @@ "post_message_api/post_message_api_test.ts", "shortcut_input_key_test.ts", "shortcut_input_test.ts", - "sea_pen/sea_pen_constants_test.ts", - "sea_pen/sea_pen_utils_test.ts", "typescript_utils/strict_query_test.ts", ] deps = [ "../..:build_ts", "//ash/webui/common/resources:build_ts", "//ash/webui/common/resources/cr_elements:build_ts", - "//ash/webui/common/resources/sea_pen:build_ts", "//third_party/polymer/v3_0:library", "//ui/webui/resources/js:build_ts", ]
diff --git a/chrome/test/data/webui/chromeos/ash_common/sea_pen/BUILD.gn b/chrome/test/data/webui/chromeos/ash_common/sea_pen/BUILD.gn new file mode 100644 index 0000000..cdb66d6 --- /dev/null +++ b/chrome/test/data/webui/chromeos/ash_common/sea_pen/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../../build_webui_tests.gni") + +build_webui_tests("build_webui_tests") { + files = [ + "sea_pen_constants_test.ts", + "sea_pen_utils_test.ts", + ] + + ts_deps = [ "//ash/webui/common/resources/sea_pen:build_ts" ] +}
diff --git a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn index c2c1375b..436c248 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn +++ b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
@@ -15,7 +15,7 @@ ] files = [ - "battery_status_card_test.js", + "battery_status_card_test.ts", "cellular_info_test.js", "connectivity_card_test.js", "cpu_card_test.js",
diff --git a/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.ts similarity index 66% rename from chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js rename to chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.ts index a68e4ce0..ecbbae6 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/battery_status_card_test.ts
@@ -10,54 +10,44 @@ import {getDiagnosticsIcon} from 'chrome://diagnostics/diagnostics_utils.js'; import {fakeBatteryChargeStatus, fakeBatteryChargeStatus2, fakeBatteryChargeStatus3, fakeBatteryHealth, fakeBatteryHealth2, fakeBatteryHealth3, fakeBatteryInfo} from 'chrome://diagnostics/fake_data.js'; import {FakeSystemDataProvider} from 'chrome://diagnostics/fake_system_data_provider.js'; -import {getSystemDataProvider, setSystemDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js'; +import {setSystemDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js'; import {RoutineSectionElement} from 'chrome://diagnostics/routine_section.js'; import {BatteryChargeStatus, BatteryHealth, BatteryInfo, ExternalPowerSource} from 'chrome://diagnostics/system_data_provider.mojom-webui.js'; import {RoutineType} from 'chrome://diagnostics/system_routine_controller.mojom-webui.js'; -import {TextBadgeElement} from 'chrome://diagnostics/text_badge.js'; +import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; +import {assert} from 'chrome://resources/js/assert.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; - -import {isChildVisible, isVisible} from '../test_util.js'; +import {isChildVisible, isVisible} from 'chrome://webui-test/test_util.js'; import * as dx_utils from './diagnostics_test_utils.js'; const BATTERY_ICON_PREFIX = 'battery-'; suite('batteryStatusCardTestSuite', function() { - /** @type {?BatteryStatusCardElement} */ - let batteryStatusElement = null; + let batteryStatusElement: BatteryStatusCardElement|null = null; - /** @type {?FakeSystemDataProvider} */ - let provider = null; + const provider: FakeSystemDataProvider = new FakeSystemDataProvider(); suiteSetup(() => { - provider = new FakeSystemDataProvider(); setSystemDataProviderForTesting(provider); }); setup(() => { - document.body.innerHTML = window.trustedTypes.emptyHTML; + document.body.innerHTML = window.trustedTypes!.emptyHTML; }); teardown(() => { - if (batteryStatusElement) { - batteryStatusElement.remove(); - } + batteryStatusElement?.remove(); batteryStatusElement = null; - - provider.reset(); + provider?.reset(); }); - /** - * @param {!BatteryInfo} batteryInfo - * @param {!Array<!BatteryChargeStatus>} batteryChargeStatus - * @param {!Array<!BatteryHealth>} batteryHealth - * @return {!Promise} - */ function initializeBatteryStatusCard( - batteryInfo, batteryChargeStatus, batteryHealth) { + batteryInfo: BatteryInfo, batteryChargeStatus: BatteryChargeStatus[], + batteryHealth: BatteryHealth[]): Promise<void> { assertFalse(!!batteryStatusElement); // Initialize the fake data. @@ -66,9 +56,8 @@ provider.setFakeBatteryInfo(batteryInfo); // Add the battery status card to the DOM. - batteryStatusElement = /** @type {!BatteryStatusCardElement} */ ( - document.createElement('battery-status-card')); - assertTrue(!!batteryStatusElement); + batteryStatusElement = document.createElement('battery-status-card'); + assert(batteryStatusElement); document.body.appendChild(batteryStatusElement); return flushTasks(); @@ -76,66 +65,35 @@ /** * Returns the routine-section from the card. - * @return {!RoutineSectionElement} */ - function getRoutineSection() { - const routineSection = /** @type {!RoutineSectionElement} */ ( - batteryStatusElement.shadowRoot.querySelector('routine-section')); - assertTrue(!!routineSection); - return routineSection; - } - - /** - * Returns the status badge. - * @return {!TextBadgeElement} - */ - function getStatusBadge() { - const routineSectionElement = getRoutineSection(); - - return /** @type {!TextBadgeElement} */ ( - routineSectionElement.shadowRoot.querySelector('#testStatusBadge')); - } - - /** - * Returns the status text. - * @return {!HTMLElement} - */ - function getStatusTextElement() { - const routineSectionElement = getRoutineSection(); - - const statusText = - /** @type {!HTMLElement} */ ( - routineSectionElement.shadowRoot.querySelector('#testStatusText')); - assertTrue(!!statusText); - return statusText; + function getRoutineSection(): RoutineSectionElement { + assert(batteryStatusElement); + return strictQuery( + 'routine-section', batteryStatusElement.shadowRoot, + RoutineSectionElement); } /** * Returns the Run Tests button from inside the routine-section. - * @return {!CrButtonElement} */ - function getRunTestsButton() { + function getRunTestsButton(): CrButtonElement { const button = dx_utils.getRunTestsButtonFromSection(getRoutineSection()); - assertTrue(!!button); + assert(button); return button; } /** * Returns whether the run tests button is disabled. - * @return {boolean} */ - function isRunTestsButtonDisabled() { + function isRunTestsButtonDisabled(): boolean { return getRunTestsButton().disabled; } - /** - * Get batteryChargeStatus.powerAdapterStatus private member for testing. - * @suppress {visibility} // access private member - * @return {!ExternalPowerSource} - */ - function getPowerAdapterStatus() { - assertTrue(!!batteryStatusElement); - return batteryStatusElement.batteryChargeStatus.powerAdapterStatus; + + function getPowerAdapterStatus(): ExternalPowerSource { + assert(batteryStatusElement); + return batteryStatusElement.getBatteryChargeStatusForTesting() + .powerAdapterStatus; } test('BatteryStatusCardPopulated', () => { @@ -145,35 +103,35 @@ dx_utils.assertTextContains( dx_utils.getDataPointValue( batteryStatusElement, '#batteryHealth'), - `${fakeBatteryHealth[0].batteryWearPercentage}`); + `${fakeBatteryHealth[0]!.batteryWearPercentage}`); dx_utils.assertTextContains( dx_utils.getDataPoint(batteryStatusElement, '#batteryHealth') .tooltipText, loadTimeData.getString('batteryHealthTooltipText')); dx_utils.assertTextContains( dx_utils.getDataPointValue(batteryStatusElement, '#cycleCount'), - `${fakeBatteryHealth[0].cycleCount}`); + `${fakeBatteryHealth[0]!.cycleCount}`); dx_utils.assertTextContains( dx_utils.getDataPoint(batteryStatusElement, '#cycleCount') .tooltipText, loadTimeData.getString('cycleCountTooltipText')); dx_utils.assertTextContains( dx_utils.getDataPointValue(batteryStatusElement, '#currentNow'), - `${fakeBatteryChargeStatus[0].currentNowMilliamps}`); + `${fakeBatteryChargeStatus[0]!.currentNowMilliamps}`); dx_utils.assertTextContains( dx_utils.getDataPoint(batteryStatusElement, '#currentNow') .tooltipText, loadTimeData.getString('currentNowTooltipText')); dx_utils.assertElementContainsText( - batteryStatusElement.shadowRoot.querySelector( + batteryStatusElement!.shadowRoot!.querySelector( '#batteryStatusChipInfo'), - `${fakeBatteryHealth[0].chargeFullDesignMilliampHours}`); + `${fakeBatteryHealth[0]!.chargeFullDesignMilliampHours}`); const barChart = dx_utils.getPercentBarChartElement(batteryStatusElement); assertEquals( - fakeBatteryHealth[0].chargeFullNowMilliampHours, barChart.max); + fakeBatteryHealth[0]!.chargeFullNowMilliampHours, barChart.max); assertEquals( - fakeBatteryChargeStatus[0].chargeNowMilliampHours, + fakeBatteryChargeStatus[0]!.chargeNowMilliampHours, barChart.value); // Verify that the data points container is visible. @@ -198,8 +156,8 @@ assertEquals( routineSectionElement.routines[0], RoutineType.kBatteryCharge); - batteryStatusElement.onBatteryChargeStatusUpdated( - fakeBatteryChargeStatus[2]); + batteryStatusElement!.onBatteryChargeStatusUpdated( + (fakeBatteryChargeStatus[2] as BatteryChargeStatus)); return flushTasks(); }) .then(() => { @@ -209,8 +167,8 @@ assertEquals( routineSectionElement.routines[0], RoutineType.kBatteryDischarge); - batteryStatusElement.onBatteryChargeStatusUpdated( - fakeBatteryChargeStatus[3]); + batteryStatusElement!.onBatteryChargeStatusUpdated( + (fakeBatteryChargeStatus[3] as BatteryChargeStatus)); return flushTasks(); }) .then(() => { @@ -220,8 +178,8 @@ routineSectionElement.additionalMessage, loadTimeData.getString('batteryChargeTestFullMessage')); assertTrue(isRunTestsButtonDisabled()); - assertTrue(isVisible(/** @type {!HTMLElement} */ ( - routineSectionElement.shadowRoot.querySelector('#messageIcon')))); + assertTrue(isVisible( + routineSectionElement.shadowRoot!.querySelector('#messageIcon'))); }); }); @@ -232,7 +190,7 @@ fakeBatteryInfo, fakeBatteryChargeStatus, fakeBatteryHealth) .then(() => { assertEquals(ExternalPowerSource.kAc, getPowerAdapterStatus()); - assertEquals(expectedBatteryIcon, batteryStatusElement.batteryIcon); + assertEquals(expectedBatteryIcon, batteryStatusElement!.batteryIcon); }); }); @@ -246,7 +204,7 @@ const expectedIconRange = '71-77'; assertEquals( getDiagnosticsIcon(BATTERY_ICON_PREFIX + expectedIconRange), - batteryStatusElement.batteryIcon); + batteryStatusElement!.batteryIcon); }); }); @@ -260,7 +218,7 @@ const expectedIconRange = 'outline'; assertEquals( getDiagnosticsIcon(BATTERY_ICON_PREFIX + expectedIconRange), - batteryStatusElement.batteryIcon); + batteryStatusElement!.batteryIcon); }); }); });
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.cc b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.cc new file mode 100644 index 0000000..7d6e583c --- /dev/null +++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.cc
@@ -0,0 +1,212 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "ash/constants/ash_features.h" +#include "ash/webui/diagnostics_ui/url_constants.h" +#include "base/strings/stringprintf.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/test/base/web_ui_mocha_browser_test.h" +#include "content/public/test/browser_test.h" + +/** + * @fileoverview Runs the WebUI resources tests. + */ + +namespace ash { + +namespace { + +class DiagnosticsAppBrowserTest : public WebUIMochaBrowserTest { + public: + DiagnosticsAppBrowserTest() { + set_test_loader_host(ash::kChromeUIDiagnosticsAppHost); + } + + protected: + void RunTestAtPath(const std::string& testFilePath) { + auto testPath = + base::StringPrintf("chromeos/diagnostics/%s", testFilePath.c_str()); + WebUIMochaBrowserTest::RunTest(testPath, "mocha.run()"); + } +}; + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, App) { + RunTestAtPath("diagnostics_app_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, BatteryStatusCard) { + RunTestAtPath("battery_status_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, CellularInfo) { + RunTestAtPath("cellular_info_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, ConnectivityCard) { + RunTestAtPath("connectivity_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, CpuCard) { + RunTestAtPath("cpu_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DataPoint) { + RunTestAtPath("data_point_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DiagnosticsNetworkIcon) { + RunTestAtPath("diagnostics_network_icon_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DiagnosticsStickyBanner) { + RunTestAtPath("diagnostics_sticky_banner_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DiagnosticsUtils) { + RunTestAtPath("diagnostics_utils_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DrawingProvider) { + RunTestAtPath("drawing_provider_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, DrawingProviderUtils) { + RunTestAtPath("drawing_provider_utils_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, EthernetInfo) { + RunTestAtPath("ethernet_info_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, FakeMojoInterface) { + RunTestAtPath("mojo_interface_provider_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, FakeNetworkHealthProvider) { + RunTestAtPath("fake_network_health_provider_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, FakeSystemDataProvider) { + RunTestAtPath("fake_system_data_provider_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, FakeSystemRoutineController) { + RunTestAtPath("fake_system_routine_controller_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, FrequencyChannelUtils) { + RunTestAtPath("frequency_channel_utils_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, IpConfigInfoDrawer) { + RunTestAtPath("ip_config_info_drawer_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, MemoryCard) { + RunTestAtPath("memory_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, NetworkCard) { + RunTestAtPath("network_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, NetworkInfo) { + RunTestAtPath("network_info_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, NetworkList) { + RunTestAtPath("network_list_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, NetworkTroubleshooting) { + RunTestAtPath("network_troubleshooting_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, OverviewCard) { + RunTestAtPath("overview_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, PercentBarChart) { + RunTestAtPath("percent_bar_chart_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RealtimeCpuChart) { + RunTestAtPath("realtime_cpu_chart_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RoutineGroup) { + RunTestAtPath("routine_group_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RoutineListExecutor) { + RunTestAtPath("routine_list_executor_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RoutineResultEntry) { + RunTestAtPath("routine_result_entry_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RoutineResultList) { + RunTestAtPath("routine_result_list_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, RoutineSection) { + RunTestAtPath("routine_section_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, SystemPage) { + RunTestAtPath("system_page_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, TextBadge) { + RunTestAtPath("text_badge_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppBrowserTest, WifiInfo) { + RunTestAtPath("wifi_info_test.js"); +} + +class DiagnosticsAppWithInputBrowserTest : public DiagnosticsAppBrowserTest { + public: + DiagnosticsAppWithInputBrowserTest() { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kEnableTouchpadsInDiagnosticsApp, + features::kEnableTouchscreensInDiagnosticsApp}, + /*disabled_features=*/{}); + set_test_loader_host(ash::kChromeUIDiagnosticsAppHost); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, AppForInputHiding) { + RunTestAtPath("diagnostics_app_input_hiding_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, InputCard) { + RunTestAtPath("input_card_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, InputList) { + RunTestAtPath("input_list_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, KeyboardTester) { + RunTestAtPath("keyboard_tester_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, TouchscreenTester) { + RunTestAtPath("touchscreen_tester_test.js"); +} + +IN_PROC_BROWSER_TEST_F(DiagnosticsAppWithInputBrowserTest, TouchpadTester) { + RunTestAtPath("touchpad_tester_test.js"); +} + +} // namespace + +} // namespace ash
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js deleted file mode 100644 index 35f0c8b1..0000000 --- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Test fixture for chrome://diagnostics. - * Unifieid polymer testing suite for diagnostics app. - * - * To run all tests in a single instance (default, faster): - * `browser_tests --gtest_filter=DiagnosticsApp*`` - * - * To run a single test suite, such as 'CpuCard': - * `browser_tests - * --gtest_filter=DiagnosticsApp_CpuCard.All` - * - * To run a single test suite, such as 'TouchscreenTester': - * `browser_tests - * --gtest_filter=DiagnosticsAppWithInput_TouchscreenTester.All` - * - */ - -GEN_INCLUDE(['//chrome/test/data/webui/chromeos/polymer_browser_test_base.js']); - -GEN('#include "ash/constants/ash_features.h"'); -GEN('#include "content/public/test/browser_test.h"'); - -const DiagnosticsApp = class extends PolymerTest { - /** @override */ - get featureList() {} -}; - -const DiagnosticsAppWithInput = class extends PolymerTest { - /** @override */ - get featureList() { - return { - enabled: [ - 'ash::features::kEnableTouchpadsInDiagnosticsApp', - 'ash::features::kEnableTouchscreensInDiagnosticsApp', - ], - }; - } -}; - -const tests = [ - ['App', 'diagnostics_app_test.js'], - ['AppForInputHiding', 'diagnostics_app_input_hiding_test.js', 'Input'], - ['BatteryStatusCard', 'battery_status_card_test.js'], - ['CellularInfo', 'cellular_info_test.js'], - ['ConnectivityCard', 'connectivity_card_test.js'], - ['CpuCard', 'cpu_card_test.js'], - ['DataPoint', 'data_point_test.js'], - ['DiagnosticsNetworkIcon', 'diagnostics_network_icon_test.js'], - ['DiagnosticsStickyBanner', 'diagnostics_sticky_banner_test.js'], - ['DiagnosticsUtils', 'diagnostics_utils_test.js'], - ['DrawingProvider', 'drawing_provider_test.js'], - ['DrawingProviderUtils', 'drawing_provider_utils_test.js'], - ['EthernetInfo', 'ethernet_info_test.js'], - ['FakeMojoInterface', 'mojo_interface_provider_test.js'], - ['FakeNetworkHealthProvider', 'fake_network_health_provider_test.js'], - ['FakeSystemDataProvider', 'fake_system_data_provider_test.js'], - ['FakeSystemRoutineContoller', 'fake_system_routine_controller_test.js'], - ['FrequencyChannelUtils', 'frequency_channel_utils_test.js'], - ['InputCard', 'input_card_test.js', 'Input'], - ['InputList', 'input_list_test.js', 'Input'], - ['IpConfigInfoDrawer', 'ip_config_info_drawer_test.js'], - ['KeyboardTester', 'keyboard_tester_test.js', 'Input'], - ['MemoryCard', 'memory_card_test.js'], - ['NetworkCard', 'network_card_test.js'], - ['NetworkInfo', 'network_info_test.js'], - ['NetworkList', 'network_list_test.js'], - ['NetworkTroubleshooting', 'network_troubleshooting_test.js'], - ['OverviewCard', 'overview_card_test.js'], - ['PercentBarChart', 'percent_bar_chart_test.js'], - ['RealtimeCpuChart', 'realtime_cpu_chart_test.js'], - ['RoutineGroup', 'routine_group_test.js'], - ['RoutineListExecutor', 'routine_list_executor_test.js'], - ['RoutineResultEntry', 'routine_result_entry_test.js'], - ['RoutineResultList', 'routine_result_list_test.js'], - ['RoutineSection', 'routine_section_test.js'], - ['SystemPage', 'system_page_test.js'], - ['TextBadge', 'text_badge_test.js'], - ['TouchscreenTester', 'touchscreen_tester_test.js', 'Input'], - ['TouchpadTester', 'touchpad_tester_test.js', 'Input'], - ['WifiInfo', 'wifi_info_test.js'], -]; - -tests.forEach(([testName, module, condition, caseName]) => { - const className = - `DiagnosticsApp${condition ? `With${condition}` : ''}_${testName}`; - - let classToExtend = DiagnosticsApp; - if (condition === 'Input') { - classToExtend = DiagnosticsAppWithInput; - } - - this[className] = class extends classToExtend { - /** @override */ - get browsePreload() { - return `chrome://diagnostics/test_loader.html` + - `?module=chromeos/diagnostics/${module}`; - } - } - - TEST_F(className, caseName || 'All', () => mocha.run()); -});
diff --git a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js index d50d02e..d93e994f 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
@@ -17,7 +17,7 @@ import {setInputDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js'; import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; -import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {assertArrayEquals, assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js index de26a03..3cf8a61 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/realtime_cpu_chart_test.js
@@ -51,7 +51,7 @@ */ function getFrameDuration() { assertTrue(!!realtimeCpuChartElement); - return realtimeCpuChartElement.frameDuration_; + return realtimeCpuChartElement.frameDuration; } /** @@ -60,7 +60,7 @@ */ function getPaddings() { assertTrue(!!realtimeCpuChartElement); - return realtimeCpuChartElement.padding_; + return realtimeCpuChartElement.padding; } /**
diff --git a/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js b/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js index 176d6ad..61d7c00f 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/touchpad_tester_test.js
@@ -8,7 +8,7 @@ import {fakeTouchDevices} from 'chrome://diagnostics/fake_data.js'; import {TouchpadTesterElement} from 'chrome://diagnostics/touchpad_tester.js'; import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; -import {assertDeepEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {MockController} from '../mock_controller.m.js';
diff --git a/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js b/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js index db424173..2b4c9a5 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/touchscreen_tester_test.js
@@ -5,7 +5,7 @@ import 'chrome://webui-test/chromeos/mojo_webui_test_support.js'; import {DialogType, SCREEN_MAX_LENGTH, TouchEventType} from 'chrome://diagnostics/touchscreen_tester.js'; -import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {MockController} from '../mock_controller.m.js';
diff --git a/chrome/test/data/webui/chromeos/fake_network_config_mojom.js b/chrome/test/data/webui/chromeos/fake_network_config_mojom.js index 65abb28..392e1dfd 100644 --- a/chrome/test/data/webui/chromeos/fake_network_config_mojom.js +++ b/chrome/test/data/webui/chromeos/fake_network_config_mojom.js
@@ -121,6 +121,7 @@ this.globalPolicy_ = /** @type {!GlobalPolicy} */ ({ + allowApnModification: true, allow_cellular_sim_lock: true, allow_only_policy_cellular_networks: false, allow_only_policy_networks_to_autoconnect: false, @@ -679,7 +680,7 @@ }); } - /** @param {!GlobalPolicy} globalPolicy */ + /** @param {!GlobalPolicy|undefined} globalPolicy */ setGlobalPolicy(globalPolicy) { this.globalPolicy_ = globalPolicy; this.onPoliciesApplied(/*userhash=*/ '');
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn index a0d901a..3bc5fc1 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn +++ b/chrome/test/data/webui/chromeos/shimless_rma/BUILD.gn
@@ -33,12 +33,12 @@ "reimaging_calibration_failed_page_test.ts", "reimaging_calibration_run_page_test.ts", "reimaging_calibration_setup_page_test.ts", - "reimaging_device_information_page_test.js", + "reimaging_device_information_page_test.ts", "reimaging_firmware_update_page_test.ts", "reimaging_provisioning_page_test.js", "repair_component_chip_test.js", "shimless_3p_diag_test.js", - "shimless_rma_app_test.js", + "shimless_rma_app_test.ts", "wrapup_finalize_page_test.js", "wrapup_repair_complete_page_test.js", "wrapup_restock_page_test.ts",
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js deleted file mode 100644 index 5889daa..0000000 --- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.js +++ /dev/null
@@ -1,794 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {PromiseResolver} from 'chrome://resources/ash/common/promise_resolver.js'; -import {fakeDeviceCustomLabels, fakeDeviceRegions, fakeDeviceSkuDescriptions, fakeDeviceSkus} from 'chrome://shimless-rma/fake_data.js'; -import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js'; -import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js'; -import {BooleanOrDefaultOptions, ReimagingDeviceInformationPage} from 'chrome://shimless-rma/reimaging_device_information_page.js'; -import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js'; -import {FeatureLevel} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js'; -import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; -import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; - -import {isVisible} from '../test_util.js'; - -const fakeSerialNumber = 'serial# 0001'; -const fakeDramPartNumber = 'dram# 0123'; - -// TODO(gavindodd) how to update selectedIndex and trigger on-change -// automatically. -/** - * onSelected*Change is not triggered automatically and the functions are - * protected. It is not possible to suppress visibility inline so this helper - * function wraps them. - * @suppress {visibility} - */ -function suppressedComponentOnSelectedChange_(component) { - component.onSelectedRegionChange('ignored'); - component.onSelectedCustomLabelChange('ignored'); - component.onSelectedSkuChange('ignored'); - component.onIsChassisBrandedChange('ignored'); - component.onDoesMeetRequirementsChange('ignored'); -} - -/** - * This function is used to verify the results of calls to - * ShimlessRMAService.setDeviceInformation. - * @param {Object} fakeShimlessService the service that will - * have a mocked "setDeviceInformation". - * @param {PromiseResolver} promiseResolver - * @param {Object} result Empty object to store call results into. - */ -function setSetDeviceInformationForMockService( - fakeShimlessService, promiseResolver, result) { - result.callCounter = 0; - fakeShimlessService.setDeviceInformation = - (resultSerialNumber, resultRegionIndex, resultSkuIndex, - resultCustomLabelIndex, resultDramPartNumber, resultIsChassisBranded, - resultHwComplianceVersion) => { - result.callCounter++; - result.serialNumber = resultSerialNumber; - result.regionIndex = resultRegionIndex; - result.customLabelIndex = resultCustomLabelIndex; - result.skuIndex = resultSkuIndex; - result.dramPartNumber = resultDramPartNumber; - result.isChassisBranded = resultIsChassisBranded; - result.hwComplianceVersion = resultHwComplianceVersion; - return promiseResolver.promise; - }; -} - -suite('reimagingDeviceInformationPageTest', function() { - /** @type {?ReimagingDeviceInformationPage} */ - let component = null; - - /** @type {?FakeShimlessRmaService} */ - let service = null; - - setup(() => { - document.body.innerHTML = trustedTypes.emptyHTML; - service = new FakeShimlessRmaService(); - setShimlessRmaServiceForTesting(service); - }); - - teardown(() => { - component.remove(); - component = null; - service.reset(); - }); - - function initializeReimagingDeviceInformationPage() { - assertFalse(!!component); - service.setGetOriginalSerialNumberResult(fakeSerialNumber); - service.setGetRegionListResult(fakeDeviceRegions); - service.setGetOriginalRegionResult(2); - service.setGetCustomLabelListResult(fakeDeviceCustomLabels); - service.setGetOriginalCustomLabelResult(3); - service.setGetSkuListResult(fakeDeviceSkus); - service.setGetSkuDescriptionListResult(fakeDeviceSkuDescriptions); - service.setGetOriginalSkuResult(1); - service.setGetOriginalDramPartNumberResult(fakeDramPartNumber); - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnsupported); - } - - /** @return {!Promise} */ - async function initializeComponent() { - component = /** @type {!ReimagingDeviceInformationPage} */ ( - document.createElement('reimaging-device-information-page')); - assertTrue(!!component); - document.body.appendChild(component); - - // A flush tasks is required to wait for the drop lists to render and set - // the initial selected index. - await flushTasks(); - - return flushTasks(); - } - - test('PageInitializes', async () => { - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - await waitAfterNextRender(component); - - const serialNumberComponent = - component.shadowRoot.querySelector('#serialNumber'); - const regionSelectComponent = - component.shadowRoot.querySelector('#regionSelect'); - const customLabelSelectComponent = - component.shadowRoot.querySelector('#customLabelSelect'); - const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect'); - const resetSerialNumberComponent = - component.shadowRoot.querySelector('#resetSerialNumber'); - const resetRegionComponent = - component.shadowRoot.querySelector('#resetRegion'); - const resetCustomLabelComponent = - component.shadowRoot.querySelector('#resetCustomLabel'); - const resetSkuComponent = component.shadowRoot.querySelector('#resetSku'); - - assertEquals(fakeSerialNumber, serialNumberComponent.value); - assertEquals(2, regionSelectComponent.selectedIndex); - assertEquals(3, customLabelSelectComponent.selectedIndex); - assertEquals(1, skuSelectComponent.selectedIndex); - assertTrue(resetSerialNumberComponent.disabled); - assertTrue(resetRegionComponent.disabled); - assertTrue(resetCustomLabelComponent.disabled); - assertTrue(resetSkuComponent.disabled); - }); - - test('NextReturnsInformation', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - - const serialNumberComponent = - component.shadowRoot.querySelector('#serialNumber'); - const regionSelectComponent = - component.shadowRoot.querySelector('#regionSelect'); - const customLabelSelectComponent = - component.shadowRoot.querySelector('#customLabelSelect'); - const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect'); - const dramPartNumberComponent = - component.shadowRoot.querySelector('#dramPartNumber'); - const expectedSerialNumber = 'expected serial number'; - const expectedRegionIndex = 0; - const expectedCustomLabelIndex = 1; - const expectedSkuIndex = 2; - const expectedDramPartNumber = 'expected dram part number'; - serialNumberComponent.value = expectedSerialNumber; - regionSelectComponent.selectedIndex = expectedRegionIndex; - customLabelSelectComponent.selectedIndex = expectedCustomLabelIndex; - skuSelectComponent.selectedIndex = expectedSkuIndex; - dramPartNumberComponent.value = expectedDramPartNumber; - // TODO(gavindodd) how to update selectedIndex and trigger on-change - // automatically. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - const setDeviceInformationResults = {}; - setSetDeviceInformationForMockService( - service, resolver, setDeviceInformationResults); - - const expectedResult = {foo: 'bar'}; - let savedResult; - component.onNextButtonClick().then((result) => savedResult = result); - // Resolve to a distinct result to confirm it was not modified. - resolver.resolve(expectedResult); - await flushTasks(); - - assertEquals(1, setDeviceInformationResults.callCounter); - assertEquals( - expectedSerialNumber, setDeviceInformationResults.serialNumber); - assertEquals(expectedRegionIndex, setDeviceInformationResults.regionIndex); - assertEquals( - expectedCustomLabelIndex, setDeviceInformationResults.customLabelIndex); - assertEquals(expectedSkuIndex, setDeviceInformationResults.skuIndex); - assertEquals( - expectedDramPartNumber, setDeviceInformationResults.dramPartNumber); - assertEquals(false, setDeviceInformationResults.isChassisBranded); - assertEquals(0, setDeviceInformationResults.hwComplianceVersion); - assertDeepEquals(expectedResult, savedResult); - }); - - test('ModifySerialNumberAndReset', async () => { - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - - component.allButtonsDisabled = false; - const serialNumber = fakeSerialNumber + 'new serial number'; - const serialNumberComponent = - component.shadowRoot.querySelector('#serialNumber'); - const resetSerialNumberComponent = - component.shadowRoot.querySelector('#resetSerialNumber'); - - assertEquals(serialNumberComponent.value, fakeSerialNumber); - assertTrue(resetSerialNumberComponent.disabled); - serialNumberComponent.value = serialNumber; - await flushTasks(); - assertFalse(resetSerialNumberComponent.disabled); - assertEquals(serialNumberComponent.value, serialNumber); - resetSerialNumberComponent.click(); - await flushTasks(); - assertEquals(serialNumberComponent.value, fakeSerialNumber); - assertTrue(resetSerialNumberComponent.disabled); - }); - - test('InputsDisabled', async () => { - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - - const serialNumberInput = - component.shadowRoot.querySelector('#serialNumber'); - const regionSelect = component.shadowRoot.querySelector('#regionSelect'); - const skuSelect = component.shadowRoot.querySelector('#skuSelect'); - const dramSelect = component.shadowRoot.querySelector('#dramPartNumber'); - const customLabelSelect = - component.shadowRoot.querySelector('#customLabelSelect'); - - component.allButtonsDisabled = false; - assertFalse(serialNumberInput.disabled); - assertFalse(regionSelect.disabled); - assertFalse(skuSelect.disabled); - assertFalse(dramSelect.disabled); - assertFalse(customLabelSelect.disabled); - - component.allButtonsDisabled = true; - assertTrue(serialNumberInput.disabled); - assertTrue(regionSelect.disabled); - assertTrue(skuSelect.disabled); - assertTrue(dramSelect.disabled); - assertTrue(customLabelSelect.disabled); - }); - - test( - 'ModifyDramPartNumberAndReset', async () => { - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - - component.allButtonsDisabled = false; - const dramPartNumber = fakeDramPartNumber + 'new part number'; - const dramPartNumberComponent = - component.shadowRoot.querySelector('#dramPartNumber'); - const resetDramPartNumberComponent = - component.shadowRoot.querySelector('#resetDramPartNumber'); - - assertEquals(dramPartNumberComponent.value, fakeDramPartNumber); - assertTrue(resetDramPartNumberComponent.disabled); - dramPartNumberComponent.value = dramPartNumber; - await flushTasks(); - assertFalse(resetDramPartNumberComponent.disabled); - assertEquals(dramPartNumberComponent.value, dramPartNumber); - resetDramPartNumberComponent.click(); - await flushTasks(); - assertEquals(dramPartNumberComponent.value, fakeDramPartNumber); - assertTrue(resetDramPartNumberComponent.disabled); - }); - - test( - 'SerialNumberUpdatesNextDisable', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - let disableNextButtonEventFired = false; - let disableNextButton = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - disableNextButton = e.detail; - }); - - const serialNumberComponent = - component.shadowRoot.querySelector('#serialNumber'); - serialNumberComponent.value = ''; - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertTrue(disableNextButton); - - disableNextButtonEventFired = false; - serialNumberComponent.value = 'valid serial number'; - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertFalse(disableNextButton); - }); - - test('RegionUpdatesNextDisable', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - let disableNextButtonEventFired = false; - let disableNextButton = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - disableNextButton = e.detail; - }); - - const regionSelectComponent = - component.shadowRoot.querySelector('#regionSelect'); - regionSelectComponent.selectedIndex = -1; - // TODO(gavindodd) how to update selectedIndex and trigger on-change - // automatically. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertTrue(disableNextButton); - - disableNextButtonEventFired = false; - regionSelectComponent.selectedIndex = 1; - // TODO(gavindodd) how to update selectedIndex and trigger on-change - // automatically. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertFalse(disableNextButton); - }); - - test('SkuUpdatesNextDisable', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - let disableNextButtonEventFired = false; - let disableNextButton = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - disableNextButton = e.detail; - }); - - const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect'); - skuSelectComponent.selectedIndex = -1; - // TODO(gavindodd) how to update selectedIndex and trigger on-change - // automatically. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertTrue(disableNextButton); - - disableNextButtonEventFired = false; - skuSelectComponent.selectedIndex = 1; - // TODO(gavindodd) how to update selectedIndex and trigger on-change - // automatically. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertFalse(disableNextButton); - }); - - test('CustomLabelUpdatesNextDisable', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - let disableNextButtonEventFired = false; - let disableNextButton = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - disableNextButton = e.detail; - }); - - const customLabelSelectComponent = - component.shadowRoot.querySelector('#customLabelSelect'); - customLabelSelectComponent.selectedIndex = -1; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertTrue(disableNextButton); - - disableNextButtonEventFired = false; - customLabelSelectComponent.selectedIndex = 1; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired); - assertFalse(disableNextButton); - }); - - test( - 'DramPartNumberDoesNotUpdateNextDisable', async () => { - const resolver = new PromiseResolver(); - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - let disableNextButtonEventFired = false; - let disableNextButton = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - disableNextButton = e.detail; - }); - - const dramPartNumberComponent = - component.shadowRoot.querySelector('#dramPartNumber'); - dramPartNumberComponent.value = ''; - await flushTasks(); - - assertFalse(disableNextButtonEventFired); - - disableNextButtonEventFired = false; - dramPartNumberComponent.value = 'valid dram part number'; - await flushTasks(); - - assertFalse(disableNextButtonEventFired); - }); - - test( - 'NextButtonState_IsChassisBranded', async () => { - // Set the compliance check flag so that the additional questions show - // up. - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - - // Set the feature level so that the additional questions show up. - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnknown); - - await initializeComponent(); - - const hwComplianceVersionElement = - component.shadowRoot.querySelector('#doesMeetRequirements'); - const isChassisBrandedElement = - component.shadowRoot.querySelector('#isChassisBranded'); - - // Set the values of the compliance question properties so that the - // next button is initially enabled. - hwComplianceVersionElement.value = BooleanOrDefaultOptions.NO; - isChassisBrandedElement.value = BooleanOrDefaultOptions.NO; - suppressedComponentOnSelectedChange_(component); - - let disableNextButtonEventFired = false; - let isNextButtonDisabled = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - isNextButtonDisabled = e.detail; - }); - - isChassisBrandedElement.value = BooleanOrDefaultOptions.YES; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired, 'Event should have fired.'); - assertFalse(isNextButtonDisabled, 'Next button should be enabled.'); - - // Reset the value of the tracking variable. - disableNextButtonEventFired = false; - - // Reset the index back to its default value, which should disable - // the next button. - isChassisBrandedElement.value = BooleanOrDefaultOptions.DEFAULT; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired, 'Event should have fired.'); - assertTrue(isNextButtonDisabled, 'Next button should be disabled.'); - }); - - test( - 'NextButtonState_HwComplianceVersion', async () => { - // Set the compliance check flag so that the additional questions show - // up. - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - - // Set the feature level so that the additional questions show up. - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnknown); - - await initializeComponent(); - - const hwComplianceVersionElement = - component.shadowRoot.querySelector('#doesMeetRequirements'); - const isChassisBrandedElement = - component.shadowRoot.querySelector('#isChassisBranded'); - - // Set the values of the compliance question properties so that the - // next button is initially enabled. - hwComplianceVersionElement.value = BooleanOrDefaultOptions.NO; - isChassisBrandedElement.value = BooleanOrDefaultOptions.NO; - suppressedComponentOnSelectedChange_(component); - - let disableNextButtonEventFired = false; - let isNextButtonDisabled = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - isNextButtonDisabled = e.detail; - }); - - // Manually update the property to trigger the observer. - hwComplianceVersionElement.value = BooleanOrDefaultOptions.YES; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired, 'Event should have fired.'); - assertFalse(isNextButtonDisabled, 'Next button should be enabled.'); - - // Reset the value of the tracking variable. - disableNextButtonEventFired = false; - - // Reset the index back to its default value, which should disable - // the next button. - hwComplianceVersionElement.value = BooleanOrDefaultOptions.DEFAULT; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired, 'Event should have fired.'); - assertTrue(isNextButtonDisabled, 'Next button should be disabled.'); - }); - - /** - * This function tests that the given featureLevel doesn't affect the state of - * the Next button. - * @param {FeatureLevel} featureLevel The feature level to test. Any value - * besides kRmadFeatureLevelUnknown will work for this test, since all - * values (besides that one) hide the compliance questions. - */ - async function expectComplianceQuestionsToNotAffectNextButtonState( - featureLevel) { - // Unknown FeatureLevel should not be passed into this function. - assert(featureLevel !== FeatureLevel.kRmadFeatureLevelUnknown); - - // Set the compliance check flag so that the additional questions show - // up if the feature level is unknown. - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - - // Set the feature level based on parameter. - service.setGetOriginalFeatureLevelResult(featureLevel); - - await initializeComponent(); - - // We can't access the Next button directly, so setup an observer to save - // the button's current state when it changes. - let disableNextButtonEventFired = false; - let isNextButtonDisabled = false; - component.addEventListener('disable-next-button', (e) => { - disableNextButtonEventFired = true; - isNextButtonDisabled = e.detail; - }); - - // Manually update a property to trigger the observer and thus give us a way - // to check the state of the Next button. - component.shadowRoot.querySelector('#serialNumber').value = 'other value'; - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertTrue(disableNextButtonEventFired, 'Event should have fired.'); - assertFalse(isNextButtonDisabled, 'Next button should be enabled.'); - } - - test( - 'NextButtonState_QuestionsNotShown_Unsupported', async () => { - await expectComplianceQuestionsToNotAffectNextButtonState( - FeatureLevel.kRmadFeatureLevelUnsupported); - }); - - test( - 'NextButtonState_QuestionsNotShown_FeatureLevel0', async () => { - await expectComplianceQuestionsToNotAffectNextButtonState( - FeatureLevel.kRmadFeatureLevel0); - }); - - test( - 'NextButtonState_QuestionsNotShown_FeatureLevel1', async () => { - await expectComplianceQuestionsToNotAffectNextButtonState( - FeatureLevel.kRmadFeatureLevel1); - }); - - test( - 'ResultsForComplianceCheckQuestions', async () => { - // Set the compliance check flag so that the additional questions show - // up. - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - - // Set the feature level so that the additional questions show up. - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnknown); - - await initializeComponent(); - - const hwComplianceVersionElement = - component.shadowRoot.querySelector('#doesMeetRequirements'); - const isChassisBrandedElement = - component.shadowRoot.querySelector('#isChassisBranded'); - - // Note that we purposefully don't test the default option for either - // field, since that disables the Next button entirely. - const scenarios = [ - { - initialHwComplianceVersionValue: BooleanOrDefaultOptions.NO, - expectedHwComplianceVersion: 0, - initialIsChassisBrandedValue: BooleanOrDefaultOptions.NO, - expectedIsChassisBranded: false, - }, - { - initialHwComplianceVersionValue: BooleanOrDefaultOptions.YES, - expectedHwComplianceVersion: 1, - initialIsChassisBrandedValue: BooleanOrDefaultOptions.YES, - expectedIsChassisBranded: true, - }, - ]; - - for (const scenario of scenarios) { - hwComplianceVersionElement.value = - scenario.initialHwComplianceVersionValue; - isChassisBrandedElement.value = scenario.initialIsChassisBrandedValue; - suppressedComponentOnSelectedChange_(component); - - const setDeviceInformationResults = {}; - const resolver = new PromiseResolver(); - setSetDeviceInformationForMockService( - service, resolver, setDeviceInformationResults); - - component.onNextButtonClick(); - resolver.resolve({}); - await flushTasks(); - assertEquals( - scenario.expectedHwComplianceVersion, - setDeviceInformationResults.hwComplianceVersion); - assertEquals( - scenario.expectedIsChassisBranded, - setDeviceInformationResults.isChassisBranded); - } - }); - - - test('ComplianceCheckDisabled', async () => { - loadTimeData.overrideValues({complianceCheckEnabled: false}); - - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - - // Expect compliance-related fields to not be present when flag is off. - assertFalse( - isVisible(component.shadowRoot.querySelector('#complianceWarning'))); - assertFalse( - isVisible(component.shadowRoot.querySelector('#isChassisBranded'))); - assertFalse( - isVisible(component.shadowRoot.querySelector('#doesMeetRequirements'))); - - // Next button should be enabled by default if the compliance check is - // disabled. - let isNextButtonDisabled = false; - component.addEventListener('disable-next-button', (e) => { - isNextButtonDisabled = e.detail; - }); - - // Trigger Next button update. - suppressedComponentOnSelectedChange_(component); - await flushTasks(); - - assertFalse(isNextButtonDisabled, 'Next button should be enabled.'); - }); - - test( - 'ComplianceCheckEnabled_Unsupported', async () => { - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnsupported); - await initializeComponent(); - - // When the FeatureLevel is set to Unsupported, no compliance-related - // fields should be shown. - assertFalse(isVisible( - component.shadowRoot.querySelector('#complianceWarning'))); - assertFalse( - isVisible(component.shadowRoot.querySelector('#isChassisBranded'))); - assertFalse(isVisible( - component.shadowRoot.querySelector('#doesMeetRequirements'))); - }); - - test( - 'ComplianceCheckEnabled_Unknown', async () => { - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevelUnknown); - await initializeComponent(); - - // When the FeatureLevel is set to Unknown, the two compliance-related - // questions should be shown. - assertFalse(isVisible( - component.shadowRoot.querySelector('#complianceWarning'))); - assertTrue( - isVisible(component.shadowRoot.querySelector('#isChassisBranded'))); - assertTrue(isVisible( - component.shadowRoot.querySelector('#doesMeetRequirements'))); - }); - - test( - 'ComplianceCheckEnabled_Level0', async () => { - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevel0); - await initializeComponent(); - - // When the FeatureLevel is set to Level 0, the compliance warning - // should be shown, and the string should indicate that the device is - // not compliant. - assertTrue(isVisible( - component.shadowRoot.querySelector('#complianceWarning'))); - assertFalse( - isVisible(component.shadowRoot.querySelector('#isChassisBranded'))); - assertFalse(isVisible( - component.shadowRoot.querySelector('#doesMeetRequirements'))); - - const complianceStatusString = - component.shadowRoot.querySelector('.compliance-status-string'); - assertEquals( - complianceStatusString.textContent.trim(), - component.i18n('confirmDeviceInfoDeviceNotCompliant')); - }); - - test( - 'ComplianceCheckEnabled_Level1', async () => { - loadTimeData.overrideValues({complianceCheckEnabled: true}); - - initializeReimagingDeviceInformationPage(); - service.setGetOriginalFeatureLevelResult( - FeatureLevel.kRmadFeatureLevel1); - await initializeComponent(); - - // When the FeatureLevel is set to Level 0, the compliance warning - // should be shown, and the string should indicate that the device is - // compliant. - assertTrue(isVisible( - component.shadowRoot.querySelector('#complianceWarning'))); - assertFalse( - isVisible(component.shadowRoot.querySelector('#isChassisBranded'))); - assertFalse(isVisible( - component.shadowRoot.querySelector('#doesMeetRequirements'))); - - const complianceStatusString = - component.shadowRoot.querySelector('.compliance-status-string'); - assertEquals( - complianceStatusString.textContent.trim(), - component.i18n('confirmDeviceInfoDeviceCompliant')); - }); - - test('SkuDescriptionEnabled', async () => { - loadTimeData.overrideValues({skuDescriptionEnabled: true}); - - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - await waitAfterNextRender(component); - - const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect'); - assertEquals( - `${fakeDeviceSkus[1]}: ${fakeDeviceSkuDescriptions[1]}`, - skuSelectComponent.value); - }); - - test('SkuDescriptionDisabled', async () => { - loadTimeData.overrideValues({skuDescriptionEnabled: false}); - - initializeReimagingDeviceInformationPage(); - await initializeComponent(); - await waitAfterNextRender(component); - - const skuSelectComponent = component.shadowRoot.querySelector('#skuSelect'); - assertEquals(`${fakeDeviceSkus[1]}`, skuSelectComponent.value); - }); - - // TODO(gavindodd): Add tests for the selection lists when they are - // reimplemented and bound. - // The standard `select` object is not bound. - // `iron-selector`, `iron-dropdown`, `cr-searchable-drop-down` and - // `paper-dropdown-menu could not be made to work. - // - // test: ReimagingDeviceInformationPageModifyRegionAndReset - // test: ReimagingDeviceInformationPageModifySkuAndReset -});
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.ts b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.ts new file mode 100644 index 0000000..9173ee5 --- /dev/null +++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_device_information_page_test.ts
@@ -0,0 +1,596 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://shimless-rma/shimless_rma.js'; + +import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; +import {CrInputElement} from 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js'; +import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {PromiseResolver} from 'chrome://resources/ash/common/promise_resolver.js'; +import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; +import {assert} from 'chrome://resources/js/assert.js'; +import {DISABLE_NEXT_BUTTON} from 'chrome://shimless-rma/events.js'; +import {fakeDeviceCustomLabels, fakeDeviceRegions, fakeDeviceSkuDescriptions, fakeDeviceSkus} from 'chrome://shimless-rma/fake_data.js'; +import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js'; +import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js'; +import {BooleanOrDefaultOptions, ReimagingDeviceInformationPage} from 'chrome://shimless-rma/reimaging_device_information_page.js'; +import {FeatureLevel, StateResult} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; + +interface SetDeviceInformationResult { + serialNumber: string; + regionIndex: number; + customLabelIndex: number; + skuIndex: number; + dramPartNumber: string; + isChassisBranded: boolean; + hwComplianceVersion: number; + callCounter: number; +} + +const originalSerialNumber = 'serial# 0001'; +const originalDramPartNumber = 'dram# 0123'; +const originalRegionSelectedIndex = 0; +const originalCustomLabelSelectedIndex = 0; +const originalSkuSelectedIndex = 0; + +const serialNumberSelector = '#serialNumber'; +const regionSelectSelector = '#regionSelect'; +const customLabelSelectSelector = '#customLabelSelect'; +const skuSelectSelector = '#skuSelect'; +const dramPartNumberSelector = '#dramPartNumber'; + +const resetSerialNumberSelector = '#resetSerialNumber'; +const resetRegionSelector = '#resetRegion'; +const resetCustomLabelSelector = '#resetCustomLabel'; +const resetSkuSelector = '#resetSku'; +const resetDramPartNumberSelector = '#resetDramPartNumber'; + +const complianceWarningSelector = '#complianceWarning'; +const meetRequirementsSelector = '#doesMeetRequirements'; +const chassisBrandedSelector = '#isChassisBranded'; +const complianceStatusStringSelector = '.compliance-status-string'; + +function createDefaultDeviceInformationResult(): SetDeviceInformationResult { + return { + serialNumber: '', + regionIndex: -1, + customLabelIndex: -1, + skuIndex: -1, + dramPartNumber: '', + isChassisBranded: false, + hwComplianceVersion: -1, + callCounter: -1, + }; +} + +// This function returns the results of calls to `setDeviceInformation()`. +function setDeviceInfoResponse( + fakeShimlessService: FakeShimlessRmaService, + promiseResolver: PromiseResolver<{stateResult: StateResult}>, + result: SetDeviceInformationResult): void { + result.callCounter = 0; + fakeShimlessService.setDeviceInformation = + (resultSerialNumber, resultRegionIndex, resultSkuIndex, + resultCustomLabelIndex, resultDramPartNumber, resultIsChassisBranded, + resultHwComplianceVersion) => { + ++result.callCounter; + result.serialNumber = resultSerialNumber; + result.regionIndex = resultRegionIndex; + result.customLabelIndex = resultCustomLabelIndex; + result.skuIndex = resultSkuIndex; + result.dramPartNumber = resultDramPartNumber; + result.isChassisBranded = resultIsChassisBranded; + result.hwComplianceVersion = resultHwComplianceVersion; + return promiseResolver.promise; + }; +} + +suite('reimagingDeviceInformationPageTest', function() { + let component: ReimagingDeviceInformationPage|null = null; + + const service: FakeShimlessRmaService = new FakeShimlessRmaService(); + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + setShimlessRmaServiceForTesting(service); + }); + + teardown(() => { + component?.remove(); + component = null; + }); + + async function initializeReimagingDeviceInformationPage(): Promise<void> { + service.setGetOriginalSerialNumberResult(originalSerialNumber); + service.setGetRegionListResult(fakeDeviceRegions); + service.setGetOriginalRegionResult(originalRegionSelectedIndex); + service.setGetCustomLabelListResult(fakeDeviceCustomLabels); + service.setGetOriginalCustomLabelResult(originalCustomLabelSelectedIndex); + service.setGetSkuListResult(fakeDeviceSkus); + service.setGetSkuDescriptionListResult(fakeDeviceSkuDescriptions); + service.setGetOriginalSkuResult(originalSkuSelectedIndex); + service.setGetOriginalDramPartNumberResult(originalDramPartNumber); + service.setGetOriginalFeatureLevelResult( + FeatureLevel.kRmadFeatureLevelUnsupported); + + assert(!component); + component = document.createElement(ReimagingDeviceInformationPage.is); + assert(component); + component.allButtonsDisabled = false; + document.body.appendChild(component); + + // `waitAfterNextRender()` required to let the dropdowns render and set + // their initial selected value. + await waitAfterNextRender(component); + return flushTasks(); + } + + async function setFeatureLevelAndReinitialize(featureLevel: FeatureLevel): + Promise<void> { + service.setGetOriginalFeatureLevelResult(featureLevel); + + component?.remove(); + component = null; + component = document.createElement(ReimagingDeviceInformationPage.is); + assert(component); + component.allButtonsDisabled = false; + document.body.appendChild(component); + + // This is required to wait for the dropdowns to render and set their + // initial selected index. + await waitAfterNextRender(component); + return flushTasks(); + } + + // Verify the page initializes with the expected components. + test('PageInitializes', async () => { + await initializeReimagingDeviceInformationPage(); + + assert(component); + assertEquals( + originalSerialNumber, + strictQuery(serialNumberSelector, component.shadowRoot, CrInputElement) + .value); + assertEquals( + originalRegionSelectedIndex, + strictQuery( + regionSelectSelector, component.shadowRoot, HTMLSelectElement) + .selectedIndex); + assertEquals( + originalCustomLabelSelectedIndex, + strictQuery( + customLabelSelectSelector, component.shadowRoot, HTMLSelectElement) + .selectedIndex); + assertEquals( + originalSkuSelectedIndex, + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement) + .selectedIndex); + assertEquals( + originalDramPartNumber, + strictQuery( + dramPartNumberSelector, component.shadowRoot, CrInputElement) + .value); + assertEquals( + `${fakeDeviceSkus[0]}: ${fakeDeviceSkuDescriptions[0]}`, + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement) + .value); + assertTrue( + strictQuery( + resetSerialNumberSelector, component.shadowRoot, CrButtonElement) + .disabled); + assertTrue( + strictQuery(resetRegionSelector, component.shadowRoot, CrButtonElement) + .disabled); + assertTrue( + strictQuery( + resetCustomLabelSelector, component.shadowRoot, CrButtonElement) + .disabled); + assertTrue( + strictQuery(resetSkuSelector, component.shadowRoot, CrButtonElement) + .disabled); + assertTrue( + strictQuery( + resetDramPartNumberSelector, component.shadowRoot, CrButtonElement) + .disabled); + }); + + // Verify clicking the next button sends the expected values from the inputs. + test('NextButtonReturnsInformation', async () => { + await initializeReimagingDeviceInformationPage(); + + + // Set new values for all the inputs. + assert(component); + const newSerialNumber = 'expected serial number'; + strictQuery(serialNumberSelector, component.shadowRoot, CrInputElement) + .value = newSerialNumber; + + const newRegionIndex = 1; + const regionSelect = strictQuery( + regionSelectSelector, component.shadowRoot, HTMLSelectElement); + regionSelect.selectedIndex = newRegionIndex; + regionSelect.dispatchEvent(new CustomEvent('change')); + + const newCustomLabelIndex = 1; + const customLabelSelect = strictQuery( + customLabelSelectSelector, component.shadowRoot, HTMLSelectElement); + customLabelSelect.selectedIndex = newCustomLabelIndex; + customLabelSelect.dispatchEvent(new CustomEvent('change')); + + const newSkuIndex = 2; + const skuSelect = + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement); + skuSelect.selectedIndex = newSkuIndex; + skuSelect.dispatchEvent(new CustomEvent('change')); + + const newDramPartNumber = 'expected dram part number'; + strictQuery(dramPartNumberSelector, component.shadowRoot, CrInputElement) + .value = newDramPartNumber; + + const setDeviceInformationResults = createDefaultDeviceInformationResult(); + const resolver = new PromiseResolver<{stateResult: StateResult}>(); + setDeviceInfoResponse(service, resolver, setDeviceInformationResults); + + component.onNextButtonClick(); + await flushTasks(); + + // Verify the new values were sent. + assertEquals(1, setDeviceInformationResults.callCounter); + assertEquals(newSerialNumber, setDeviceInformationResults.serialNumber); + assertEquals(newRegionIndex, setDeviceInformationResults.regionIndex); + assertEquals( + newCustomLabelIndex, setDeviceInformationResults.customLabelIndex); + assertEquals(newSkuIndex, setDeviceInformationResults.skuIndex); + assertEquals(newDramPartNumber, setDeviceInformationResults.dramPartNumber); + assertEquals(false, setDeviceInformationResults.isChassisBranded); + assertEquals(0, setDeviceInformationResults.hwComplianceVersion); + }); + + // Verify clicking the reset buttons set the inputs to their original values. + test('ModifyValuesAndClickReset', async () => { + await initializeReimagingDeviceInformationPage(); + + assert(component); + const resetSerialNumberButton = strictQuery( + resetSerialNumberSelector, component.shadowRoot, CrButtonElement); + const resetRegionButton = + strictQuery(resetRegionSelector, component.shadowRoot, CrButtonElement); + const resetCustomLabelButton = strictQuery( + resetCustomLabelSelector, component.shadowRoot, CrButtonElement); + const resetSkuButton = + strictQuery(resetSkuSelector, component.shadowRoot, CrButtonElement); + const resetDramPartNumberButton = strictQuery( + resetDramPartNumberSelector, component.shadowRoot, CrButtonElement); + + assertTrue(resetSerialNumberButton.disabled); + assertTrue(resetRegionButton.disabled); + assertTrue(resetCustomLabelButton.disabled); + assertTrue(resetSkuButton.disabled); + assertTrue(resetDramPartNumberButton.disabled); + + // Update all input values and expect all the reset buttons to enable. + const serialNumberSelect = + strictQuery(serialNumberSelector, component.shadowRoot, CrInputElement); + serialNumberSelect.value = 'temp serial number'; + + const regionSelect = strictQuery( + regionSelectSelector, component.shadowRoot, HTMLSelectElement); + regionSelect.selectedIndex = originalRegionSelectedIndex + 1; + regionSelect.dispatchEvent(new CustomEvent('change')); + + const customLabelSelect = strictQuery( + customLabelSelectSelector, component.shadowRoot, HTMLSelectElement); + customLabelSelect.selectedIndex = originalCustomLabelSelectedIndex + 1; + customLabelSelect.dispatchEvent(new CustomEvent('change')); + + const skuSelect = + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement); + skuSelect.selectedIndex = originalSkuSelectedIndex + 1; + skuSelect.dispatchEvent(new CustomEvent('change')); + + const dramPartNumberSelect = strictQuery( + dramPartNumberSelector, component.shadowRoot, CrInputElement); + dramPartNumberSelect.value = 'temp dram number'; + + // Click all the reset buttons and expect the inputs to revert back to their + // original values. + assertFalse(resetSerialNumberButton.disabled); + assertFalse(resetRegionButton.disabled); + assertFalse(resetCustomLabelButton.disabled); + assertFalse(resetSkuButton.disabled); + assertFalse(resetDramPartNumberButton.disabled); + resetSerialNumberButton.click(); + resetRegionButton.click(); + resetCustomLabelButton.click(); + resetSkuButton.click(); + resetDramPartNumberButton.click(); + + // All the inputs should be back to their original values. + assertEquals(originalSerialNumber, serialNumberSelect.value); + assertEquals(originalRegionSelectedIndex, regionSelect.selectedIndex); + assertEquals( + originalCustomLabelSelectedIndex, customLabelSelect.selectedIndex); + assertEquals(originalSkuSelectedIndex, skuSelect.selectedIndex); + assertEquals(originalDramPartNumber, dramPartNumberSelect.value); + }); + + // Verify when `allButtonsDisabled` is set all inputs are disabled. + test('InputsDisabled', async () => { + await initializeReimagingDeviceInformationPage(); + + assert(component); + const serialNumberSelect = + strictQuery(serialNumberSelector, component.shadowRoot, CrInputElement); + const regionSelect = strictQuery( + regionSelectSelector, component.shadowRoot, HTMLSelectElement); + const customLabelSelect = strictQuery( + customLabelSelectSelector, component.shadowRoot, HTMLSelectElement); + const skuSelect = + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement); + const dramPartNumberSelect = strictQuery( + dramPartNumberSelector, component.shadowRoot, CrInputElement); + + assertFalse(serialNumberSelect.disabled); + assertFalse(regionSelect.disabled); + assertFalse(customLabelSelect.disabled); + assertFalse(skuSelect.disabled); + assertFalse(dramPartNumberSelect.disabled); + + component.allButtonsDisabled = true; + assertTrue(serialNumberSelect.disabled); + assertTrue(regionSelect.disabled); + assertTrue(customLabelSelect.disabled); + assertTrue(skuSelect.disabled); + assertTrue(dramPartNumberSelect.disabled); + }); + + // Verify the next button gets disabled when the inputs has invalid values. + test('InvalidValueDisablesTheNextButton', async () => { + await initializeReimagingDeviceInformationPage(); + + // Set the serial number to blank, ensure the next button is disabled, + // then replace the value and see the next button enabled. + assert(component); + let disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + const serialNumberSelect = + strictQuery(serialNumberSelector, component.shadowRoot, CrInputElement); + serialNumberSelect.value = ''; + let disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + let enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + serialNumberSelect.value = 'value'; + let enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + + // Set the region to an invalid option, ensure the next button is + // disabled, then replace the value and see the next button enabled. + disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + const regionSelect = strictQuery( + regionSelectSelector, component.shadowRoot, HTMLSelectElement); + regionSelect.selectedIndex = -1; + regionSelect.dispatchEvent(new CustomEvent('change')); + disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + regionSelect.selectedIndex = originalRegionSelectedIndex; + regionSelect.dispatchEvent(new CustomEvent('change')); + enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + + // Set the custom label to an invalid option, ensure the next button is + // disabled, then replace the value and see the next button enabled. + disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + const customLabelSelect = strictQuery( + customLabelSelectSelector, component.shadowRoot, HTMLSelectElement); + customLabelSelect.selectedIndex = -1; + customLabelSelect.dispatchEvent(new CustomEvent('change')); + disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + customLabelSelect.selectedIndex = originalCustomLabelSelectedIndex; + customLabelSelect.dispatchEvent(new CustomEvent('change')); + enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + + // Set the sku to an invalid option, ensure the next button is disabled, + // then replace the value and see the next button enabled. + disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + const skuSelect = + strictQuery(skuSelectSelector, component.shadowRoot, HTMLSelectElement); + skuSelect.selectedIndex = -1; + skuSelect.dispatchEvent(new CustomEvent('change')); + disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + skuSelect.selectedIndex = originalSkuSelectedIndex; + skuSelect.dispatchEvent(new CustomEvent('change')); + enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + }); + + // Verify the next button gets disabled when the compliance questions are set + // to their default options. + test('NextButtonDisabledDefaultCompliance', async () => { + // Set the compliance check flag so that the additional questions show + // up. + loadTimeData.overrideValues({complianceCheckEnabled: true}); + + await initializeReimagingDeviceInformationPage(); + // Set the feature level so that the additional questions show up. + await setFeatureLevelAndReinitialize(FeatureLevel.kRmadFeatureLevelUnknown); + + assert(component); + const hwComplianceVersionElement = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLSelectElement); + const isChassisBrandedElement = strictQuery( + chassisBrandedSelector, component.shadowRoot, HTMLSelectElement); + + // Set the values of the compliance question properties so that the + // next button is initially enabled. + hwComplianceVersionElement.value = BooleanOrDefaultOptions.NO; + hwComplianceVersionElement.dispatchEvent(new CustomEvent('change')); + isChassisBrandedElement.value = BooleanOrDefaultOptions.NO; + isChassisBrandedElement.dispatchEvent(new CustomEvent('change')); + + // Set the compliance version to an invalid option, ensure the next + // button is disabled, then set to valid value and see the next button + // enabled. + let disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + hwComplianceVersionElement.value = BooleanOrDefaultOptions.DEFAULT; + hwComplianceVersionElement.dispatchEvent(new CustomEvent('change')); + let disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + let enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + hwComplianceVersionElement.value = BooleanOrDefaultOptions.YES; + hwComplianceVersionElement.dispatchEvent(new CustomEvent('change')); + let enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + + // Set the chassis branded version to an invalid option, ensure the next + // button is disabled, then set to valid value and see the next button + // enabled. + disableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + isChassisBrandedElement.value = BooleanOrDefaultOptions.DEFAULT; + isChassisBrandedElement.dispatchEvent(new CustomEvent('change')); + disableEventResponse = await disableNextButtonEvent; + assertTrue(disableEventResponse.detail); + + enableNextButtonEvent = eventToPromise(DISABLE_NEXT_BUTTON, component); + isChassisBrandedElement.value = BooleanOrDefaultOptions.YES; + isChassisBrandedElement.dispatchEvent(new CustomEvent('change')); + enableEventResponse = await enableNextButtonEvent; + assertFalse(enableEventResponse.detail); + }); + + // Verify the correct info is sent based on the current compliance questions + // values. + test('ResultsForComplianceCheckQuestions', async () => { + // Set the compliance check flag so that the additional questions show + // up. + loadTimeData.overrideValues({complianceCheckEnabled: true}); + + await initializeReimagingDeviceInformationPage(); + // Set the feature level so that the additional questions show up. + await setFeatureLevelAndReinitialize(FeatureLevel.kRmadFeatureLevelUnknown); + + assert(component); + const hwComplianceVersionElement = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLSelectElement); + const isChassisBrandedElement = strictQuery( + chassisBrandedSelector, component.shadowRoot, HTMLSelectElement); + + // Set both compliance question answers to NO. + hwComplianceVersionElement.value = BooleanOrDefaultOptions.NO; + hwComplianceVersionElement.dispatchEvent(new CustomEvent('change')); + isChassisBrandedElement.value = BooleanOrDefaultOptions.NO; + isChassisBrandedElement.dispatchEvent(new CustomEvent('change')); + + const resolver = new PromiseResolver<{stateResult: StateResult}>(); + let setDeviceInformationResults = createDefaultDeviceInformationResult(); + setDeviceInfoResponse(service, resolver, setDeviceInformationResults); + + // Click the next button and verify the returned results. + component.onNextButtonClick(); + await flushTasks(); + let expectedHwComplianceVersion = 0; + assertEquals( + expectedHwComplianceVersion, + setDeviceInformationResults.hwComplianceVersion); + assertFalse(setDeviceInformationResults.isChassisBranded); + + // Set both compliance question answers to YES. + hwComplianceVersionElement.value = BooleanOrDefaultOptions.YES; + hwComplianceVersionElement.dispatchEvent(new CustomEvent('change')); + isChassisBrandedElement.value = BooleanOrDefaultOptions.YES; + isChassisBrandedElement.dispatchEvent(new CustomEvent('change')); + + setDeviceInformationResults = createDefaultDeviceInformationResult(); + setDeviceInfoResponse(service, resolver, setDeviceInformationResults); + + // Click the next button and verify the updated results. + component.onNextButtonClick(); + await flushTasks(); + expectedHwComplianceVersion = 1; + assertEquals( + expectedHwComplianceVersion, + setDeviceInformationResults.hwComplianceVersion); + assertTrue(setDeviceInformationResults.isChassisBranded); + }); + + // Verify the correct warnings and text are displayed based on the current + // feature level. + test('WarningsByFeatureLevel', async () => { + loadTimeData.overrideValues({complianceCheckEnabled: true}); + + await initializeReimagingDeviceInformationPage(); + // Set the feature level so no compliance info shows. + await setFeatureLevelAndReinitialize( + FeatureLevel.kRmadFeatureLevelUnsupported); + + assert(component); + let complianceWarning = strictQuery( + complianceWarningSelector, component.shadowRoot, HTMLElement); + let meetRequirements = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLElement); + let chassisBranded = + strictQuery(chassisBrandedSelector, component.shadowRoot, HTMLElement); + + // When the FeatureLevel is set to Unsupported, no compliance-related + // fields should be shown. + assertFalse(isVisible(complianceWarning)); + assertFalse(isVisible(meetRequirements)); + assertFalse(isVisible(chassisBranded)); + + await setFeatureLevelAndReinitialize(FeatureLevel.kRmadFeatureLevelUnknown); + complianceWarning = strictQuery( + complianceWarningSelector, component.shadowRoot, HTMLElement); + meetRequirements = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLElement); + chassisBranded = + strictQuery(chassisBrandedSelector, component.shadowRoot, HTMLElement); + assertFalse(isVisible(complianceWarning)); + assertTrue(isVisible(meetRequirements)); + assertTrue(isVisible(chassisBranded)); + + await setFeatureLevelAndReinitialize(FeatureLevel.kRmadFeatureLevel0); + complianceWarning = strictQuery( + complianceWarningSelector, component.shadowRoot, HTMLElement); + meetRequirements = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLElement); + chassisBranded = + strictQuery(chassisBrandedSelector, component.shadowRoot, HTMLElement); + assertTrue(isVisible(complianceWarning)); + assertFalse(isVisible(meetRequirements)); + assertFalse(isVisible(chassisBranded)); + assertEquals( + loadTimeData.getString('confirmDeviceInfoDeviceNotCompliant'), + strictQuery( + complianceStatusStringSelector, component.shadowRoot, HTMLElement) + .textContent!.trim()); + + await setFeatureLevelAndReinitialize(FeatureLevel.kRmadFeatureLevel1); + complianceWarning = strictQuery( + complianceWarningSelector, component.shadowRoot, HTMLElement); + meetRequirements = strictQuery( + meetRequirementsSelector, component.shadowRoot, HTMLElement); + chassisBranded = + strictQuery(chassisBrandedSelector, component.shadowRoot, HTMLElement); + assertTrue(isVisible(complianceWarning)); + assertFalse(isVisible(meetRequirements)); + assertFalse(isVisible(chassisBranded)); + assertEquals( + loadTimeData.getString('confirmDeviceInfoDeviceCompliant'), + strictQuery( + complianceStatusStringSelector, component.shadowRoot, HTMLElement) + .textContent!.trim()); + }); +});
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js deleted file mode 100644 index 6248875..0000000 --- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.js +++ /dev/null
@@ -1,881 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {PromiseResolver} from 'chrome://resources/ash/common/promise_resolver.js'; -import {fakeCalibrationComponentsWithFails, fakeChromeVersion, fakeStates} from 'chrome://shimless-rma/fake_data.js'; -import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js'; -import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js'; -import {ButtonState, ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js'; -import {RmadErrorCode, State, StateResult} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js'; -import {disableAllButtons, enableAllButtons} from 'chrome://shimless-rma/shimless_rma_util.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; - -import {eventToPromise, isVisible} from '../test_util.js'; - -suite('shimlessRMAAppTest', function() { - /** @type {?ShimlessRma} */ - let component = null; - - /** @type {?FakeShimlessRmaService} */ - let service = null; - - setup(() => { - document.body.innerHTML = trustedTypes.emptyHTML; - service = new FakeShimlessRmaService(); - setShimlessRmaServiceForTesting(service); - }); - - teardown(() => { - component.remove(); - component = null; - document.body.innerHTML = trustedTypes.emptyHTML; - service.reset(); - }); - - /** - * @param {!Array<!StateResult>} states - * @param {string} chromeVersion - */ - function initializeShimlessRMAApp(states, chromeVersion) { - assertFalse(!!component); - - // Initialize the fake data. - service.setStates(states); - service.setGetCurrentOsVersionResult(chromeVersion); - service.setCheckForOsUpdatesResult('fake version'); - - component = - /** @type {!ShimlessRma} */ (document.createElement('shimless-rma')); - assertTrue(!!component); - document.body.appendChild(component); - - return flushTasks(); - } - - /** - * Utility function to assert navigation buttons - * TODO(joonbug): expand to cover assertion of ButtonState - */ - function assertNavButtons() { - const nextButton = component.shadowRoot.querySelector('#next'); - const exitButton = component.shadowRoot.querySelector('#exit'); - const backButton = component.shadowRoot.querySelector('#back'); - assertTrue(!!nextButton); - assertTrue(!!exitButton); - assertTrue(!!backButton); - } - - /** - * Utility function to click next button - * @return {Promise} - */ - function clickNext() { - // Make sure the Next button is enabled. - component.dispatchEvent(new CustomEvent( - 'disable-next-button', - {bubbles: true, composed: true, detail: false}, - )); - const nextButton = component.shadowRoot.querySelector('#next'); - nextButton.click(); - return flushTasks(); - } - - /** - * Utility function to click back button - * @return {Promise} - */ - function clickBack() { - const backButton = component.shadowRoot.querySelector('#back'); - backButton.click(); - return flushTasks(); - } - - /** - * Utility function to click exit button - * @return {Promise} - */ - function clickExit() { - const exitButton = component.shadowRoot.querySelector('#exit'); - exitButton.click(); - return flushTasks(); - } - - /** - * @param {string} buttonNameSelector - * @return {!Promise} - */ - function clickButton(buttonNameSelector) { - assertTrue(!!component); - - const button = component.shadowRoot.querySelector(buttonNameSelector); - button.click(); - return flushTasks(); - } - - /** @return {!Promise} */ - function openLogsDialog() { - component.dispatchEvent(new CustomEvent( - 'open-logs-dialog', - {bubbles: true, composed: true}, - )); - return flushTasks(); - } - - test('ShimlessRMALoaded', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - assertNavButtons(); - - // The Hardware Error page should be hidden by default. - const hardwareErrorPage = - component.shadowRoot.querySelector('hardware-error-page'); - assertFalse(!!hardwareErrorPage); - }); - - test('ShimlessRMABasicNavigation', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const prevButton = component.shadowRoot.querySelector('#back'); - const exitButton = component.shadowRoot.querySelector('#exit'); - assertTrue(!!prevButton); - assertTrue(!!exitButton); - - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - assertTrue(!!initialPage); - assertFalse(initialPage.hidden); - assertFalse(initialPage.allButtonsDisabled); - assertTrue(prevButton.hidden); - assertTrue(exitButton.hidden); - - // This enables the next button on the landing page. - service.triggerHardwareVerificationStatusObserver(true, '', 0); - await flushTasks(); - await clickNext(); - - const selectNetworkPage = - component.shadowRoot.querySelector('onboarding-network-page'); - assertTrue(!!selectNetworkPage); - assertFalse(selectNetworkPage.hidden); - assertTrue(!!initialPage); - assertTrue(initialPage.hidden); - assertFalse(prevButton.hidden); - assertFalse(exitButton.hidden); - - prevButton.click(); - await flushTasks(); - - // components page should not be destroyed. - assertTrue(!!selectNetworkPage); - assertTrue(selectNetworkPage.hidden); - assertFalse(initialPage.hidden); - assertTrue(prevButton.hidden); - assertTrue(exitButton.hidden); - }); - - test('ShimlessRMAExit', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - let abortRmaCount = 0; - service.abortRma = () => { - abortRmaCount++; - return Promise.resolve(RmadErrorCode.kOk); - }; - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - const exitButton = component.shadowRoot.querySelector('#exit'); - - assertFalse(initialPage.allButtonsDisabled); - exitButton.click(); - - const exitDialog = component.shadowRoot.querySelector('#exitDialog'); - assertTrue(exitDialog.open); - - const confirmExitButton = - component.shadowRoot.querySelector('#confirmExitDialogButton'); - assertTrue(!!confirmExitButton); - confirmExitButton.click(); - await flushTasks(); - - assertEquals(1, abortRmaCount); - assertTrue(initialPage.allButtonsDisabled); - }); - - test('CancelExitDialog', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - let abortRmaCount = 0; - service.abortRma = () => { - abortRmaCount++; - return Promise.resolve(RmadErrorCode.kOk); - }; - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - const exitButton = component.shadowRoot.querySelector('#exit'); - - assertFalse(initialPage.allButtonsDisabled); - exitButton.click(); - const exitDialog = component.shadowRoot.querySelector('#exitDialog'); - assertTrue(exitDialog.open); - component.shadowRoot.querySelector('#cancelExitDialogButton').click(); - assertFalse(exitDialog.open); - await flushTasks(); - - assertEquals(0, abortRmaCount); - assertFalse(initialPage.allButtonsDisabled); - }); - - test('NextButtonClickedOnReady', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - assertTrue(!!initialPage); - - const resolver = new PromiseResolver(); - initialPage.onNextButtonClick = () => resolver.promise; - assertFalse(initialPage.allButtonsDisabled); - - await clickNext(); - assertFalse(initialPage.hidden); - assertTrue(initialPage.allButtonsDisabled); - - resolver.resolve( - {stateResult: {state: State.kUpdateOs, error: RmadErrorCode.kOk}}); - await flushTasks(); - - const updatePage = - component.shadowRoot.querySelector('onboarding-update-page'); - assertTrue(!!updatePage); - assertFalse(updatePage.hidden); - assertFalse(updatePage.allButtonsDisabled); - assertTrue(initialPage.hidden); - }); - - test('NextButtonClickedOnNotReady', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - assertTrue(!!initialPage); - - const resolver = new PromiseResolver(); - initialPage.onNextButtonClick = () => resolver.promise; - - await clickNext(); - assertFalse(initialPage.hidden); - - resolver.reject(); - await flushTasks(); - - assertFalse(initialPage.hidden); - }); - - test('UpdateButtonState', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const backButton = component.shadowRoot.querySelector('#back'); - assertTrue(!!backButton); - assertTrue(backButton.hidden); - - component.updateButtonState('buttonBack', ButtonState.VISIBLE); - await flushTasks(); - - assertFalse(backButton.hidden); - }); - - test('UpdateNextButtonLabel', async () => { - await initializeShimlessRMAApp( - [{ - state: State.kSelectComponents, - canExit: true, - canGoBack: true, - error: RmadErrorCode.kOk, - }], - fakeChromeVersion[0]); - - const nextButton = component.shadowRoot.querySelector('#nextButtonLabel'); - assertEquals( - loadTimeData.getString('nextButtonLabel'), - nextButton.textContent.trim()); - - component.dispatchEvent(new CustomEvent( - 'set-next-button-label', - {bubbles: true, composed: true, detail: 'skipButtonLabel'}, - )); - assertEquals( - loadTimeData.getString('skipButtonLabel'), - nextButton.textContent.trim()); - }); - - test('NextButtonSpinner', async () => { - await initializeShimlessRMAApp( - [{ - state: State.kSelectComponents, - canExit: true, - canGoBack: true, - error: RmadErrorCode.kOk, - }], - fakeChromeVersion[0]); - - const initialPage = - component.shadowRoot.querySelector('onboarding-select-components-page'); - assertTrue(!!initialPage); - - const nextButtonSpinner = - component.shadowRoot.querySelector('#nextButtonSpinner'); - const backButtonSpinner = - component.shadowRoot.querySelector('#backButtonSpinner'); - const exitButtonSpinner = - component.shadowRoot.querySelector('#exitButtonSpinner'); - - // Next spinner - const nextResolver = new PromiseResolver(); - initialPage.onNextButtonClick = () => nextResolver.promise; - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - - await clickNext(); - assertFalse(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - - nextResolver.resolve({state: State.kUpdateOs, error: RmadErrorCode.kOk}); - await flushTasks(); - - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - }); - - test('BackButtonSpinner', async () => { - await initializeShimlessRMAApp( - [{ - state: State.kSelectComponents, - canExit: true, - canGoBack: true, - error: RmadErrorCode.kOk, - }], - fakeChromeVersion[0]); - - const initialPage = - component.shadowRoot.querySelector('onboarding-select-components-page'); - assertTrue(!!initialPage); - - const nextButtonSpinner = - component.shadowRoot.querySelector('#nextButtonSpinner'); - const backButtonSpinner = - component.shadowRoot.querySelector('#backButtonSpinner'); - const exitButtonSpinner = - component.shadowRoot.querySelector('#exitButtonSpinner'); - - // Back spinner - const backResolver = new PromiseResolver(); - service.transitionPreviousState = () => { - return backResolver.promise; - }; - await clickBack(); - assertTrue(nextButtonSpinner.hidden); - assertFalse(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - - backResolver.resolve( - {stateResult: {state: State.kUpdateOs, error: RmadErrorCode.kOk}}); - await flushTasks(); - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - }); - - test('ExitButtonSpinner', async () => { - await initializeShimlessRMAApp( - [{ - state: State.kSelectComponents, - canExit: true, - canGoBack: true, - error: RmadErrorCode.kOk, - }], - fakeChromeVersion[0]); - - const initialPage = - component.shadowRoot.querySelector('onboarding-select-components-page'); - assertTrue(!!initialPage); - - const nextButtonSpinner = - component.shadowRoot.querySelector('#nextButtonSpinner'); - const backButtonSpinner = - component.shadowRoot.querySelector('#backButtonSpinner'); - const exitButtonSpinner = - component.shadowRoot.querySelector('#exitButtonSpinner'); - - // Exit spinner - const exitResolver = new PromiseResolver(); - service.abortRma = () => { - return exitResolver.promise; - }; - await clickExit(); - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - - const exitDialog = component.shadowRoot.querySelector('#exitDialog'); - assertTrue(exitDialog.open); - await component.shadowRoot.querySelector('#confirmExitDialogButton') - .click(); - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertFalse(exitButtonSpinner.hidden); - - exitResolver.resolve({state: State.kUpdateOs, error: RmadErrorCode.kOk}); - await flushTasks(); - assertTrue(nextButtonSpinner.hidden); - assertTrue(backButtonSpinner.hidden); - assertTrue(exitButtonSpinner.hidden); - }); - - test('AllButtonsDisabled', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const nextButton = component.shadowRoot.querySelector('#next'); - const backButton = component.shadowRoot.querySelector('#back'); - const exitButton = component.shadowRoot.querySelector('#exit'); - const busyStateOverlay = /** @type {!HTMLElement} */ ( - component.shadowRoot.querySelector('#busyStateOverlay')); - - assertFalse(nextButton.disabled); - assertFalse(backButton.disabled); - assertFalse(exitButton.disabled); - - disableAllButtons(component, /*showBusyStateOverlay=*/ false); - assertTrue(nextButton.disabled); - assertTrue(backButton.disabled); - assertTrue(exitButton.disabled); - assertFalse(isVisible(busyStateOverlay)); - - disableAllButtons(component, /*showBusyStateOverlay=*/ true); - assertTrue(isVisible(busyStateOverlay)); - - enableAllButtons(component); - assertFalse(nextButton.disabled); - assertFalse(backButton.disabled); - assertFalse(exitButton.disabled); - assertFalse(isVisible(busyStateOverlay)); - }); - - test('ExitButtonClickEventIsHandled', async () => { - const resolver = new PromiseResolver(); - - await initializeShimlessRMAApp( - [{ - state: State.kWelcomeScreen, - canExit: true, - canGoBack: true, - error: RmadErrorCode.kOk, - }], - fakeChromeVersion[0]); - - let callCounter = 0; - service.abortRma = () => { - callCounter++; - return resolver.promise; - }; - - component.dispatchEvent(new CustomEvent( - 'click-exit-button', - {bubbles: true, composed: true}, - )); - - await flushTasks(); - const exitDialog = component.shadowRoot.querySelector('#exitDialog'); - assertTrue(exitDialog.open); - assertEquals(0, callCounter); - }); - - test('TransitionStateListener', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - // Confirm starting on the landing page. - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - assertTrue(!!initialPage); - - // Attempt to transition OS Update page. - component.dispatchEvent(new CustomEvent( - 'transition-state', - { - bubbles: true, - composed: true, - detail: () => Promise.resolve({ - stateResult: {state: State.kUpdateOs, error: RmadErrorCode.kOk}, - }), - }, - )); - await flushTasks(); - - // Confirm transition to the OS Update page. - const updatePage = - component.shadowRoot.querySelector('onboarding-update-page'); - assertTrue(!!updatePage); - }); - - test('StateResultCanExitCanGoBack', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - // Confirm starting on the landing page. - const initialPage = - component.shadowRoot.querySelector('onboarding-landing-page'); - assertTrue(!!initialPage); - - component.dispatchEvent(new CustomEvent( - 'transition-state', - { - bubbles: true, - composed: true, - detail: () => Promise.resolve({ - stateResult: { - state: State.kUpdateOs, - error: RmadErrorCode.kOk, - canExit: false, - canGoBack: false, - }, - }), - }, - )); - await flushTasks(); - - // Confirm transition to the OS Update page. - const updatePage = - component.shadowRoot.querySelector('onboarding-update-page'); - assertTrue(!!updatePage); - const backButton = component.shadowRoot.querySelector('#back'); - const exitButton = component.shadowRoot.querySelector('#exit'); - - // Both buttons should be hidden due to the `stateResult` response. - assertTrue(backButton.hidden); - assertTrue(exitButton.hidden); - - // Initialize the fake data. - service.setGetCalibrationComponentListResult( - fakeCalibrationComponentsWithFails); - - // Attempt to transition to Calibration Failed page. - component.dispatchEvent(new CustomEvent( - 'transition-state', - { - bubbles: true, - composed: true, - detail: () => Promise.resolve({ - stateResult: { - state: State.kCheckCalibration, - error: RmadErrorCode.kOk, - canExit: false, - canGoBack: false, - }, - }), - }, - )); - await flushTasks(); - - // The exit button should never be hidden for the Calibration failed page. - assertTrue(backButton.hidden); - assertFalse(exitButton.hidden); - }); - - test('HardwareErrorEventIsHandled', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - component.dispatchEvent(new CustomEvent( - 'fatal-hardware-error', - { - bubbles: true, - composed: true, - detail: { - rmadErrorCode: RmadErrorCode.kProvisioningFailed, - fatalErrorCode: 1001, - }, - }, - )); - - await flushTasks(); - - // Confirm transition to the Hardware Error page. - const hardwareErrorPage = - component.shadowRoot.querySelector('hardware-error-page'); - assertTrue(!!hardwareErrorPage); - }); - - test('RebootErrorCodeResultsInShowingRebootPage', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - // Emulate platform sending a reboot error code. - component.dispatchEvent(new CustomEvent( - 'transition-state', - { - bubbles: true, - composed: true, - detail: () => Promise.resolve({ - stateResult: { - state: State.kWPDisableComplete, - error: RmadErrorCode.kExpectReboot, - }, - }), - }, - )); - await flushTasks(); - - // Confirm transition to the reboot page. - const rebootPage = component.shadowRoot.querySelector('reboot-page'); - assertTrue(!!rebootPage); - }); - - test('ShutdownErrorCodeResultsInShowingShutdownPage', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - // Emulate platform sending a shut down error code. - component.dispatchEvent(new CustomEvent( - 'transition-state', - { - bubbles: true, - composed: true, - detail: () => Promise.resolve({ - stateResult: { - state: State.kWPDisableComplete, - error: RmadErrorCode.kExpectShutdown, - }, - }), - }, - )); - await flushTasks(); - - // Confirm transition to the reboot page. - const rebootPage = component.shadowRoot.querySelector('reboot-page'); - assertTrue(!!rebootPage); - }); - - test('SaveLogsToUsb', async () => { - const resolver = new PromiseResolver(); - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - service.triggerExternalDiskObserver(true, 0); - await flushTasks(); - - let callCount = 0; - service.saveLog = () => { - callCount++; - return resolver.promise; - }; - - await openLogsDialog(); - assertTrue( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - - // Attempt to save the logs. - await clickButton('#saveLogDialogButton'); - const savePath = 'save/path'; - resolver.resolve({savePath: {path: savePath}, error: RmadErrorCode.kOk}); - await flushTasks(); - - assertEquals(1, callCount); - - // The save log button should be replaced by the done button. - assertFalse( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - assertTrue(isVisible( - component.shadowRoot.querySelector('#logSaveDoneDialogButton'))); - assertEquals( - loadTimeData.getStringF('rmaLogsSaveSuccessText', savePath), - component.shadowRoot.querySelector('#logSavedStatusText') - .textContent.trim()); - - // Close the logs dialog. - await clickButton('#logSaveDoneDialogButton'); - await flushTasks(); - - // Open the logs dialog and verify we are at the original state with the - // Save Log button displayed. - await openLogsDialog(); - assertTrue( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - }); - - test('SaveLogFails', async () => { - const resolver = new PromiseResolver(); - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - service.triggerExternalDiskObserver(true, 0); - await flushTasks(); - - let callCount = 0; - service.saveLog = () => { - callCount++; - return resolver.promise; - }; - - await openLogsDialog(); - assertTrue( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - - // Attempt to save the logs but it fails. - await clickButton('#saveLogDialogButton'); - resolver.resolve( - {savePath: 'save/path', error: RmadErrorCode.kCannotSaveLog}); - await flushTasks(); - - assertEquals(1, callCount); - - // The save log button should be replaced by the done button and the retry - // button. - assertFalse( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - assertTrue(isVisible( - component.shadowRoot.querySelector('#logSaveDoneDialogButton'))); - assertTrue( - isVisible(component.shadowRoot.querySelector('#logRetryDialogButton'))); - assertEquals( - loadTimeData.getString('rmaLogsSaveFailText'), - component.shadowRoot.querySelector('#logSavedStatusText') - .textContent.trim()); - - // Click the retry button and verify that it retries saving the logs. - await clickButton('#logRetryDialogButton'); - resolver.resolve( - {savePath: 'save/path', error: RmadErrorCode.kCannotSaveLog}); - await flushTasks(); - - assertEquals(2, callCount); - }); - - test('SaveLogFailsUsbNotFound', async () => { - const resolver = new PromiseResolver(); - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - service.triggerExternalDiskObserver(true, 0); - await flushTasks(); - - let callCount = 0; - service.saveLog = () => { - callCount++; - return resolver.promise; - }; - - await openLogsDialog(); - assertTrue( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - - // Attempt to save the logs but it fails because the USB is not detected. - await clickButton('#saveLogDialogButton'); - resolver.resolve( - {savePath: 'save/path', error: RmadErrorCode.kUsbNotFound}); - await flushTasks(); - - assertEquals(1, callCount); - - // The save log button should be replaced by the done button and the retry - // button. - assertFalse( - isVisible(component.shadowRoot.querySelector('#saveLogDialogButton'))); - assertTrue(isVisible( - component.shadowRoot.querySelector('#logSaveDoneDialogButton'))); - assertTrue( - isVisible(component.shadowRoot.querySelector('#logRetryDialogButton'))); - assertEquals( - loadTimeData.getString('rmaLogsSaveUsbNotFound'), - component.shadowRoot.querySelector('#logSavedStatusText') - .textContent.trim()); - }); - - test('ExternalDiskConnectedShowsUsbActionButtons', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - service.triggerExternalDiskObserver(true, 0); - await flushTasks(); - - const logConnectUsbMessageContainer = - component.shadowRoot.querySelector('#logConnectUsbMessageContainer'); - assertTrue(!!logConnectUsbMessageContainer); - assertTrue(logConnectUsbMessageContainer.hidden); - - const saveLogButtonContainer = - component.shadowRoot.querySelector('#saveLogButtonContainer'); - assertTrue(!!saveLogButtonContainer); - assertFalse(saveLogButtonContainer.hidden); - - const logSaveAttemptButtonContainer = - component.shadowRoot.querySelector('#logSaveAttemptButtonContainer'); - assertTrue(!!logSaveAttemptButtonContainer); - assertTrue(logSaveAttemptButtonContainer.hidden); - }); - - test('ExternalDiskDisconnectedShowsMissingUsbMessage', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - service.triggerExternalDiskObserver(false, 0); - await flushTasks(); - - const logConnectUsbMessageContainer = - component.shadowRoot.querySelector('#logConnectUsbMessageContainer'); - assertTrue(!!logConnectUsbMessageContainer); - assertFalse(logConnectUsbMessageContainer.hidden); - - const saveLogButtonContainer = - component.shadowRoot.querySelector('#saveLogButtonContainer'); - assertTrue(!!saveLogButtonContainer); - assertTrue(saveLogButtonContainer.hidden); - - const logSaveAttemptButtonContainer = - component.shadowRoot.querySelector('#logSaveAttemptButtonContainer'); - assertTrue(!!logSaveAttemptButtonContainer); - assertTrue(logSaveAttemptButtonContainer.hidden); - }); - - test('LogsDialogCloses', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - await openLogsDialog(); - - const logsDialog = component.shadowRoot.querySelector('#logsDialog'); - assertTrue(logsDialog.open); - - await clickButton('#closeLogDialogButton'); - - assertTrue(!!logsDialog); - assertFalse(logsDialog.open); - - // Verify logs dialog can be closed when the USB is unplugged. - service.triggerExternalDiskObserver(false, 0); - await openLogsDialog(); - assertTrue(logsDialog.open); - - await clickButton('#closeLogDialogButton'); - - assertTrue(!!logsDialog); - assertFalse(logsDialog.open); - }); - - test('KeyboardShortcutOpensLogsDialog', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - // Confirm logs dialog starts closed. - const logsDialog = component.shadowRoot.querySelector('#logsDialog'); - assertTrue(!!logsDialog); - assertFalse(logsDialog.open); - - const keydownEventPromise = eventToPromise('keydown', component); - component.dispatchEvent(new KeyboardEvent( - 'keydown', - { - bubbles: true, - composed: true, - key: 'L', - altKey: true, - shiftKey: true, - }, - )); - - await keydownEventPromise; - assertTrue(logsDialog.open); - }); - - test('3pDiagLoaded', async () => { - await initializeShimlessRMAApp(fakeStates, fakeChromeVersion[0]); - - const diagnostics = - component.shadowRoot.querySelector('#shimless3pDiagnostics'); - assertTrue(typeof diagnostics.launch3pDiagnostics === 'function'); - }); -});
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.ts b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.ts new file mode 100644 index 0000000..8d970ad --- /dev/null +++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_app_test.ts
@@ -0,0 +1,793 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://shimless-rma/shimless_rma.js'; + +import {CrButtonElement} from 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; +import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; +import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {PromiseResolver} from 'chrome://resources/ash/common/promise_resolver.js'; +import {strictQuery} from 'chrome://resources/ash/common/typescript_utils/strict_query.js'; +import {assert} from 'chrome://resources/js/assert.js'; +import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js'; +import {CLICK_EXIT_BUTTON, DISABLE_NEXT_BUTTON, FATAL_HARDWARE_ERROR, OPEN_LOGS_DIALOG, SET_NEXT_BUTTON_LABEL, TRANSITION_STATE} from 'chrome://shimless-rma/events.js'; +import {fakeCalibrationComponentsWithFails, fakeStates} from 'chrome://shimless-rma/fake_data.js'; +import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js'; +import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js'; +import {OnboardingLandingPage} from 'chrome://shimless-rma/onboarding_landing_page.js'; +import {OnboardingSelectComponentsPageElement} from 'chrome://shimless-rma/onboarding_select_components_page.js'; +import {ButtonState, ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js'; +import {RmadErrorCode, State, StateResult} from 'chrome://shimless-rma/shimless_rma.mojom-webui.js'; +import {disableAllButtons, enableAllButtons} from 'chrome://shimless-rma/shimless_rma_util.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js'; +import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; +import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; + +suite('shimlessRMAAppTest', function() { + let component: ShimlessRma|null = null; + + const service: FakeShimlessRmaService = new FakeShimlessRmaService(); + + const nextButtonSelector = '#next'; + const backButtonSelector = '#back'; + const exitButtonSelector = '#exit'; + + const exitDialogSelector = '#exitDialog'; + const confirmExitButtonSelector = '#confirmExitDialogButton'; + const cancelExitButtonSelector = '#cancelExitDialogButton'; + + const saveLogButtonSelector = '#saveLogDialogButton'; + const logSaveDoneButtonSelector = '#logSaveDoneDialogButton'; + const logRetryButtonSelector = '#logRetryDialogButton'; + const logSavedStatusSelector = '#logSavedStatusText'; + const closeLogsDialogButtonSelector = '#closeLogDialogButton'; + + const logsDialogSelector = '#logsDialog'; + const logConnectUsbMessageSelector = '#logConnectUsbMessageContainer'; + const saveLogContainerSelector = '#saveLogButtonContainer'; + + const hardwareErrorPageSelector = 'hardware-error-page'; + const landingPageSelector = 'onboarding-landing-page'; + const networkPageSelector = 'onboarding-network-page'; + const updatePageSelector = 'onboarding-update-page'; + const rebootPageSelector = 'reboot-page'; + const selectComponentsPageSelector = 'onboarding-select-components-page'; + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + setShimlessRmaServiceForTesting(service); + }); + + teardown(() => { + component?.remove(); + component = null; + }); + + function initializeShimlessRMAApp(states: StateResult[] = fakeStates): + Promise<void> { + // Initialize the fake data. + service.setStates(states); + service.setGetCurrentOsVersionResult(/* version= */ ''); + service.setCheckForOsUpdatesResult(/* version= */ ''); + + assert(!component); + component = document.createElement(ShimlessRma.is); + assert(component); + document.body.appendChild(component); + + return flushTasks(); + } + + // Utility function to click next button + function clickNext(): Promise<void> { + assert(component); + // Make sure the Next button is enabled. + component.dispatchEvent(new CustomEvent( + DISABLE_NEXT_BUTTON, + {bubbles: true, composed: true, detail: false}, + )); + strictQuery(nextButtonSelector, component.shadowRoot, CrButtonElement) + .click(); + return flushTasks(); + } + + // Utility function to click back button + function clickBack(): Promise<void> { + assert(component); + strictQuery(backButtonSelector, component.shadowRoot, CrButtonElement) + .click(); + return flushTasks(); + } + + // Utility function to click exit button + function clickExit(): Promise<void> { + assert(component); + strictQuery(exitButtonSelector, component.shadowRoot, CrButtonElement) + .click(); + return flushTasks(); + } + + function clickButton(buttonNameSelector: string): Promise<void> { + assert(component); + strictQuery(buttonNameSelector, component.shadowRoot, CrButtonElement) + .click(); + return flushTasks(); + } + + function openLogsDialog(): Promise<void> { + assert(component); + component.dispatchEvent(new CustomEvent( + OPEN_LOGS_DIALOG, + {bubbles: true, composed: true}, + )); + return flushTasks(); + } + + // Verify the correct components are loaded + test('ShimlessRMALoaded', async () => { + await initializeShimlessRMAApp(); + + assert(component); + assert( + strictQuery(nextButtonSelector, component.shadowRoot, CrButtonElement)); + assert( + strictQuery(exitButtonSelector, component.shadowRoot, CrButtonElement)); + assert( + strictQuery(backButtonSelector, component.shadowRoot, CrButtonElement)); + + // The Hardware Error page should be hidden by default. + assert(!(component.shadowRoot!.querySelector(hardwareErrorPageSelector))); + // 3P Diagnostics should be loaded. + strictQuery('#shimless3pDiagnostics', component.shadowRoot, HTMLElement); + }); + + // Verify clicking the next button goes to the next page and the back button + // goes to the previous page. + test('ShimlessRMABasicNavigation', async () => { + await initializeShimlessRMAApp(); + + assert(component); + const initialPage = + strictQuery(landingPageSelector, component.shadowRoot, HTMLElement); + assertFalse(initialPage.hidden); + + // This enables the next button on the landing page. + assert(service); + service.triggerHardwareVerificationStatusObserver( + /* isCompliant= */ true, /* errorMessage= */ '', /* delayMs= */ 0); + await flushTasks(); + await clickNext(); + + const selectNetworkPage = + strictQuery(networkPageSelector, component.shadowRoot, HTMLElement); + assertFalse(selectNetworkPage.hidden); + + // Click the back button and expect the networking page to be hidden but not + // destroyed. + await clickBack(); + assert(selectNetworkPage); + assertTrue(selectNetworkPage.hidden); + assertFalse(initialPage.hidden); + }); + + // Verify clicking the exit button attempts to abort Shimless RMA. + test('ShimlessRMAExit', async () => { + await initializeShimlessRMAApp(); + let abortRmaCount = 0; + service.abortRma = () => { + ++abortRmaCount; + return Promise.resolve({error: RmadErrorCode.kOk}); + }; + + await clickExit(); + + assert(component); + const exitDialog = + strictQuery(exitDialogSelector, component.shadowRoot, CrDialogElement); + assertTrue(exitDialog.open); + strictQuery( + confirmExitButtonSelector, component.shadowRoot, CrButtonElement) + .click(); + await flushTasks(); + + assertFalse(exitDialog.open); + assertEquals(1, abortRmaCount); + }); + + // Verify clicking the cancel exit button doesn't attempt to abort Shimless + // RMA. + test('CancelExitDialog', async () => { + await initializeShimlessRMAApp(); + let abortRmaCount = 0; + service.abortRma = () => { + ++abortRmaCount; + return Promise.resolve({error: RmadErrorCode.kOk}); + }; + + await clickExit(); + + assert(component); + const exitDialog = + strictQuery(exitDialogSelector, component.shadowRoot, CrDialogElement); + assertTrue(exitDialog.open); + strictQuery(cancelExitButtonSelector, component.shadowRoot, CrButtonElement) + .click(); + await flushTasks(); + + assertFalse(exitDialog.open); + assertEquals(0, abortRmaCount); + }); + + // Verify the page change doesn't change when the next button click is + // rejected. + test('NextButtonClickedOnNotReady', async () => { + await initializeShimlessRMAApp(); + + // Confirm the initial page is visible. + assert(component); + const initialPage = strictQuery( + landingPageSelector, component.shadowRoot, OnboardingLandingPage); + assertFalse(initialPage.hidden); + + // Click the next button expecting to go to the next page. + const resolver = new PromiseResolver<{stateResult: StateResult}>(); + initialPage.onNextButtonClick = () => resolver.promise; + await clickNext(); + + // Reject the next button click and confirm the initial page is still + // visible. + resolver.reject(); + await flushTasks(); + assertFalse(initialPage.hidden); + }); + + // Verify the back button becomes visible when protected. + test('UpdateBackButtonVisibility', async () => { + await initializeShimlessRMAApp(); + + assert(component); + const backButton = + strictQuery(backButtonSelector, component.shadowRoot, CrButtonElement); + assertTrue(backButton.hidden); + + component.updateButtonState( + /* buttonName= */ 'buttonBack', ButtonState.VISIBLE); + await flushTasks(); + + assertFalse(backButton.hidden); + }); + + // Verify the next button label updates to "Skip" when requested. + test('UpdateNextButtonLabel', async () => { + await initializeShimlessRMAApp([{ + state: State.kSelectComponents, + canExit: true, + canGoBack: true, + error: RmadErrorCode.kOk, + }]); + + assert(component); + const nextButtonLabel = + strictQuery('#nextButtonLabel', component.shadowRoot, HTMLElement); + assertEquals( + loadTimeData.getString('nextButtonLabel'), + nextButtonLabel.textContent!.trim()); + + // Trigger the next button to update its label. + component.dispatchEvent(new CustomEvent( + SET_NEXT_BUTTON_LABEL, + {bubbles: true, composed: true, detail: 'skipButtonLabel'}, + )); + assertEquals( + loadTimeData.getString('skipButtonLabel'), + nextButtonLabel.textContent!.trim()); + }); + + // Verify the correct button spinners are showing based on the current state. + test('ButtonSpinnerStates', async () => { + await initializeShimlessRMAApp([{ + state: State.kSelectComponents, + canExit: true, + canGoBack: true, + error: RmadErrorCode.kOk, + }]); + + assert(component); + const nextButtonSpinner = + strictQuery('#nextButtonSpinner', component.shadowRoot, HTMLElement); + const backButtonSpinner = + strictQuery('#backButtonSpinner', component.shadowRoot, HTMLElement); + const exitButtonSpinner = + strictQuery('#exitButtonSpinner', component.shadowRoot, HTMLElement); + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + // Next spinner + const nextResolver = new PromiseResolver<{stateResult: StateResult}>(); + strictQuery( + selectComponentsPageSelector, component.shadowRoot, + OnboardingSelectComponentsPageElement) + .onNextButtonClick = () => nextResolver.promise; + + await clickNext(); + assertFalse(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + nextResolver.resolve({ + stateResult: { + state: State.kUpdateOs, + error: RmadErrorCode.kOk, + canExit: false, + canGoBack: false, + }, + }); + await flushTasks(); + + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + // Back spinner + const backResolver = new PromiseResolver<{stateResult: StateResult}>(); + assert(service); + service.transitionPreviousState = () => { + return backResolver.promise; + }; + + await clickBack(); + assertTrue(nextButtonSpinner.hidden); + assertFalse(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + backResolver.resolve({ + stateResult: { + state: State.kUpdateOs, + error: RmadErrorCode.kOk, + canExit: false, + canGoBack: false, + }, + }); + await flushTasks(); + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + // Exit spinner + const exitResolver = new PromiseResolver<{error: RmadErrorCode}>(); + service.abortRma = () => { + return exitResolver.promise; + }; + await clickExit(); + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + + assert(component); + await clickButton(confirmExitButtonSelector); + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertFalse(exitButtonSpinner.hidden); + + exitResolver.resolve({error: RmadErrorCode.kOk}); + await flushTasks(); + assertTrue(nextButtonSpinner.hidden); + assertTrue(backButtonSpinner.hidden); + assertTrue(exitButtonSpinner.hidden); + }); + + // Verify when requested, all buttons are disabled with busy state overlay + // visible. + test('AllButtonsDisabled', async () => { + await initializeShimlessRMAApp(); + + assert(component); + const nextButton = + strictQuery(nextButtonSelector, component.shadowRoot, CrButtonElement); + const backButton = + strictQuery(nextButtonSelector, component.shadowRoot, CrButtonElement); + const exitButton = + strictQuery(exitButtonSelector, component.shadowRoot, CrButtonElement); + const busyStateOverlay = + strictQuery('#busyStateOverlay', component.shadowRoot, HTMLElement); + + assertFalse(nextButton.disabled); + assertFalse(backButton.disabled); + assertFalse(exitButton.disabled); + + disableAllButtons(component, /* showBusyStateOverlay= */ false); + assertTrue(nextButton.disabled); + assertTrue(backButton.disabled); + assertTrue(exitButton.disabled); + assertFalse(isVisible(busyStateOverlay)); + + disableAllButtons(component, /* showBusyStateOverlay= */ true); + assertTrue(isVisible(busyStateOverlay)); + + enableAllButtons(component); + assertFalse(nextButton.disabled); + assertFalse(backButton.disabled); + assertFalse(exitButton.disabled); + assertFalse(isVisible(busyStateOverlay)); + }); + + // Verify the exit button event opens the exit dialog. + test('ExitButtonClickEventIsHandled', async () => { + await initializeShimlessRMAApp(); + + let callCounter = 0; + const resolver = new PromiseResolver<{error: RmadErrorCode}>(); + assert(service); + service.abortRma = () => { + ++callCounter; + return resolver.promise; + }; + + assert(component); + component.dispatchEvent(new CustomEvent( + CLICK_EXIT_BUTTON, + {bubbles: true, composed: true}, + )); + + await flushTasks(); + assertTrue( + strictQuery(exitDialogSelector, component.shadowRoot, CrDialogElement) + .open); + assertEquals(0, callCounter); + }); + + // Verify the "transition state" event is transitions to the requested page. + test('TransitionStateListener', async () => { + await initializeShimlessRMAApp(); + + // Attempt to transition OS Update page. + assert(component); + component.dispatchEvent(new CustomEvent( + TRANSITION_STATE, + { + bubbles: true, + composed: true, + detail: () => Promise.resolve({ + stateResult: {state: State.kUpdateOs, error: RmadErrorCode.kOk}, + canExit: false, + canGoBack: false, + }), + }, + )); + await flushTasks(); + + // Confirm transition to the OS Update page. + assert(strictQuery(updatePageSelector, component.shadowRoot, HTMLElement)); + + // Both buttons should be hidden due to the `stateResult` response. + assertTrue( + strictQuery(backButtonSelector, component.shadowRoot, CrButtonElement) + .hidden); + assertTrue( + strictQuery(exitButtonSelector, component.shadowRoot, CrButtonElement) + .hidden); + }); + + // Verify the back button can't be hidden on the failed calibartion page. + test('FailedCalibrationHiddenExitButton', async () => { + await initializeShimlessRMAApp(); + + // Initialize the fake data. + assert(service); + service.setGetCalibrationComponentListResult( + fakeCalibrationComponentsWithFails); + + // Transition to Calibration Failed page but attempt to hide the back button + // by setting `canGoBack` to false. + assert(component); + component.dispatchEvent(new CustomEvent( + 'transition-state', + { + bubbles: true, + composed: true, + detail: () => Promise.resolve({ + stateResult: { + state: State.kCheckCalibration, + error: RmadErrorCode.kOk, + canExit: false, + canGoBack: false, + }, + }), + }, + )); + await flushTasks(); + + // The back button will be hidden but the exit button should never be hidden + // for the Calibration failed page. + assertTrue( + strictQuery(backButtonSelector, component.shadowRoot, CrButtonElement) + .hidden); + assertFalse( + strictQuery(exitButtonSelector, component.shadowRoot, CrButtonElement) + .hidden); + }); + + // Verify the "fatal hardware error" event launches the hardware error page. + test('HardwareErrorEventIsHandled', async () => { + await initializeShimlessRMAApp(); + + assert(component); + component.dispatchEvent(new CustomEvent( + FATAL_HARDWARE_ERROR, + { + bubbles: true, + composed: true, + detail: { + rmadErrorCode: RmadErrorCode.kProvisioningFailed, + fatalErrorCode: 1001, + }, + }, + )); + + await flushTasks(); + + // Confirm transition to the Hardware Error page. + assert(strictQuery( + hardwareErrorPageSelector, component.shadowRoot, HTMLElement)); + }); + + // Verify the getting the `kExpectReboot` code transitions to the reboot page. + test('RebootErrorCodeResultsInShowingRebootPage', async () => { + await initializeShimlessRMAApp(); + + // Emulate platform sending a reboot error code. + assert(component); + component.dispatchEvent(new CustomEvent( + TRANSITION_STATE, + { + bubbles: true, + composed: true, + detail: () => Promise.resolve({ + stateResult: { + state: State.kWPDisableComplete, + error: RmadErrorCode.kExpectReboot, + }, + }), + }, + )); + await flushTasks(); + + // Confirm transition to the reboot page. + assert(strictQuery(rebootPageSelector, component.shadowRoot, HTMLElement)); + }); + + // Verify the getting the `kExpectShutdown` code transitions to the reboot + // page. + test('ShutdownErrorCodeResultsInRebootPage', async () => { + await initializeShimlessRMAApp(); + + // Emulate platform sending a shut down error code. + assert(component); + component.dispatchEvent(new CustomEvent( + TRANSITION_STATE, + { + bubbles: true, + composed: true, + detail: () => Promise.resolve({ + stateResult: { + state: State.kWPDisableComplete, + error: RmadErrorCode.kExpectShutdown, + }, + }), + }, + )); + await flushTasks(); + + // Confirm transition to the reboot page. + assert(strictQuery(rebootPageSelector, component.shadowRoot, HTMLElement)); + }); + + // Verify logs can be saved via the save logs dialog. + test('SaveLogsToUsb', async () => { + await initializeShimlessRMAApp(); + + assert(service); + service.triggerExternalDiskObserver(/* detected= */ true, /* delayMs= */ 0); + await flushTasks(); + + let saveLogCallCount = 0; + const resolver = + new PromiseResolver<{savePath: FilePath, error: RmadErrorCode}>(); + service.saveLog = () => { + ++saveLogCallCount; + return resolver.promise; + }; + + await openLogsDialog(); + + // Attempt to save the logs. + await clickButton(saveLogButtonSelector); + const savePath = 'save/path'; + resolver.resolve({savePath: {path: savePath}, error: RmadErrorCode.kOk}); + await flushTasks(); + + assertEquals(1, saveLogCallCount); + + // The save log button should be replaced by the done button. + assert(component); + assertFalse(isVisible(strictQuery( + saveLogButtonSelector, component.shadowRoot, CrButtonElement))); + assertTrue(isVisible(strictQuery( + logSaveDoneButtonSelector, component.shadowRoot, CrButtonElement))); + assertEquals( + loadTimeData.getStringF('rmaLogsSaveSuccessText', savePath), + strictQuery(logSavedStatusSelector, component.shadowRoot, HTMLElement) + .textContent!.trim()); + + // Close the logs dialog. + await clickButton(logSaveDoneButtonSelector); + await flushTasks(); + + // Open the logs dialog and verify we are at the original state with the + // Save Log button displayed. + await openLogsDialog(); + assertTrue(isVisible(strictQuery( + saveLogButtonSelector, component.shadowRoot, CrButtonElement))); + }); + + // Verify the save logs dialog shows error messasges for a failed save and + // allows for a retry. + test('SaveLogFails', async () => { + await initializeShimlessRMAApp(); + + assert(service); + service.triggerExternalDiskObserver(/* detected= */ true, /* delayMs= */ 0); + await flushTasks(); + + let saveLogCallCount = 0; + const resolver = + new PromiseResolver<{savePath: FilePath, error: RmadErrorCode}>(); + service.saveLog = () => { + ++saveLogCallCount; + return resolver.promise; + }; + + // Attempt to save the logs but it fails. + await openLogsDialog(); + await clickButton(saveLogButtonSelector); + resolver.resolve( + {savePath: {'path': 'save/path'}, error: RmadErrorCode.kCannotSaveLog}); + await flushTasks(); + + assertEquals(1, saveLogCallCount); + + // The save log button should be replaced by the done button and the retry + // button. + assert(component); + assertFalse(isVisible(strictQuery( + saveLogButtonSelector, component.shadowRoot, CrButtonElement))); + assertTrue(isVisible(strictQuery( + logRetryButtonSelector, component.shadowRoot, CrButtonElement))); + assertEquals( + loadTimeData.getString('rmaLogsSaveFailText'), + strictQuery(logSavedStatusSelector, component.shadowRoot, HTMLElement) + .textContent!.trim()); + + // Click the retry button and verify that it retries saving the logs. + await clickButton(logRetryButtonSelector); + resolver.resolve( + {savePath: {'path': 'save/path'}, error: RmadErrorCode.kCannotSaveLog}); + await flushTasks(); + + assertEquals(2, saveLogCallCount); + }); + + // Verify the correct message is shown for USB not found when saving logs. + test('SaveLogFailsUsbNotFound', async () => { + await initializeShimlessRMAApp(); + + assert(service); + service.triggerExternalDiskObserver(/* detected= */ true, /* delayMs= */ 0); + await flushTasks(); + + const resolver = + new PromiseResolver<{savePath: FilePath, error: RmadErrorCode}>(); + service.saveLog = () => { + return resolver.promise; + }; + + // Attempt to save the logs but it fails because the USB is not detected. + await openLogsDialog(); + await clickButton(saveLogButtonSelector); + resolver.resolve( + {savePath: {path: 'save/path'}, error: RmadErrorCode.kUsbNotFound}); + await flushTasks(); + + // The save log button should be replaced by the done button and the retry + // button. + assert(component); + assertFalse(isVisible(strictQuery( + saveLogButtonSelector, component.shadowRoot, CrButtonElement))); + // await waitAfterNextRender(strictQuery(logRetryButtonSelector, + // component.shadowRoot, CrButtonElement)); await flushTasks(); + assertTrue(isVisible(strictQuery( + logRetryButtonSelector, component.shadowRoot, CrButtonElement))); + assertEquals( + loadTimeData.getString('rmaLogsSaveUsbNotFound'), + strictQuery(logSavedStatusSelector, component.shadowRoot, HTMLElement) + .textContent!.trim()); + }); + + // Verify the correct message is shown for USB connected or disconnected. + test('ExternalDiskConnectedShowsUsbActionButtons', async () => { + await initializeShimlessRMAApp(); + + assert(component); + const logConnectUsbMessageContainer = strictQuery( + logConnectUsbMessageSelector, component.shadowRoot, HTMLElement); + const saveLogButtonContainer = strictQuery( + saveLogContainerSelector, component.shadowRoot, HTMLElement); + + // When an external disk is connected, verify the "save log" message is + // displayed. + assert(service); + service.triggerExternalDiskObserver(/* detected= */ true, /* delayMs= */ 0); + await flushTasks(); + assertTrue(logConnectUsbMessageContainer.hidden); + assertFalse(saveLogButtonContainer.hidden); + + // When an eexternal disk isn't connected, verify the "connect a USB" + // message is displayed. + service.triggerExternalDiskObserver( + /* detected= */ false, /* delayMs= */ 0); + await flushTasks(); + assertFalse(logConnectUsbMessageContainer.hidden); + assertTrue(saveLogButtonContainer.hidden); + }); + + // Verify the save logs dialog can be closed even after the USB is unplugged. + test('LogsDialogCloses', async () => { + await initializeShimlessRMAApp(); + + await openLogsDialog(); + assert(component); + const logsDialog = + strictQuery(logsDialogSelector, component.shadowRoot, CrDialogElement); + assertTrue(logsDialog.open); + + await clickButton(closeLogsDialogButtonSelector); + assertFalse(logsDialog.open); + + // Verify logs dialog can be closed when the USB is unplugged. + service.triggerExternalDiskObserver(false, 0); + await openLogsDialog(); + assertTrue(logsDialog.open); + + await clickButton(closeLogsDialogButtonSelector); + assertFalse(logsDialog.open); + }); + + // Verify the Alt+Shift+L keyboard shortcut opens the logs dialog. + test('KeyboardShortcutOpensLogsDialog', async () => { + await initializeShimlessRMAApp(); + + // Confirm logs dialog starts closed. + assert(component); + const logsDialog = + strictQuery(logsDialogSelector, component.shadowRoot, CrDialogElement); + assertFalse(logsDialog.open); + + // Invoke the Shimless logs keyboard shortcut. + const keydownEventPromise = eventToPromise('keydown', component); + component.dispatchEvent(new KeyboardEvent( + 'keydown', + { + bubbles: true, + composed: true, + key: 'L', + altKey: true, + shiftKey: true, + }, + )); + + await keydownEventPromise; + assertTrue(logsDialog.open); + }); +});
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.cc b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.cc index 786f5ba..f1afa9e 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.cc +++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.cc
@@ -139,6 +139,15 @@ RunTest("chromeos/shimless_rma/wrapup_restock_page_test.js", "mocha.run()"); } +IN_PROC_BROWSER_TEST_F(ShimlessRmaBrowserTest, DeviceInformationPage) { + RunTest("chromeos/shimless_rma/reimaging_device_information_page_test.js", + "mocha.run()"); +} + +IN_PROC_BROWSER_TEST_F(ShimlessRmaBrowserTest, ShimlessRmaAppPage) { + RunTest("chromeos/shimless_rma/shimless_rma_app_test.js", "mocha.run()"); +} + } // namespace } // namespace ash
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js index b462e09..f15e6b4 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
@@ -33,14 +33,9 @@ }; const tests = [ - [ - 'ReimagingDeviceInformationPageTest', - 'reimaging_device_information_page_test.js' - ], ['ReimagingProvisioningPageTest', 'reimaging_provisioning_page_test.js'], ['RepairComponentChipTest', 'repair_component_chip_test.js'], ['Shimless3pDiagTest', 'shimless_3p_diag_test.js'], - ['ShimlessRMAAppTest', 'shimless_rma_app_test.js'], ['WrapupFinalizePageTest', 'wrapup_finalize_page_test.js'], ['WrapupRepairCompletePageTest', 'wrapup_repair_complete_page_test.js'], [
diff --git a/chrome/test/data/webui/cr_components/history_clusters/horizontal_carousel_test.ts b/chrome/test/data/webui/cr_components/history_clusters/horizontal_carousel_test.ts index 18ff933..fd96ccaa 100644 --- a/chrome/test/data/webui/cr_components/history_clusters/horizontal_carousel_test.ts +++ b/chrome/test/data/webui/cr_components/history_clusters/horizontal_carousel_test.ts
@@ -17,8 +17,6 @@ }); test('CarouselResizeUpdatesButtons', async () => { - document.documentElement.setAttribute('chrome-refresh-2023', 'true'); - const carousel = carouselElement!.$.carouselContainer; assertTrue(!!carousel); carousel.style.width = '600px';
diff --git a/chrome/test/data/webui/downloads/item_test.ts b/chrome/test/data/webui/downloads/item_test.ts index c6b5696..f1d7034 100644 --- a/chrome/test/data/webui/downloads/item_test.ts +++ b/chrome/test/data/webui/downloads/item_test.ts
@@ -632,6 +632,7 @@ assertFalse(item.getMoreActionsMenu().open); }); + // <if expr="_google_chrome"> test('ESBDownloadRowPromoShownAndClicked', async () => { const item = document.createElement('downloads-item'); document.body.innerHTML = window.trustedTypes!.emptyHTML; @@ -671,4 +672,5 @@ const esbPromo = item.shadowRoot!.querySelector('#esb-download-row-promo'); assertFalse(isVisible(esbPromo)); }); + // </if> });
diff --git a/chrome/test/data/webui/downloads/manager_test.ts b/chrome/test/data/webui/downloads/manager_test.ts index d66f673..cea6180 100644 --- a/chrome/test/data/webui/downloads/manager_test.ts +++ b/chrome/test/data/webui/downloads/manager_test.ts
@@ -349,6 +349,7 @@ assertFalse(isVisible(dialog)); }); + // <if expr="_google_chrome"> test( 'shouldShowEsbPromotion returns true on first dangerous download', async () => { @@ -401,4 +402,5 @@ assertTrue(itemList[0]!.showEsbPromotion); assertFalse(itemList[1]!.showEsbPromotion); }); + // </if> });
diff --git a/chrome/test/data/webui/history/history_app_test.ts b/chrome/test/data/webui/history/history_app_test.ts index a8e9b9b..49514ac 100644 --- a/chrome/test/data/webui/history/history_app_test.ts +++ b/chrome/test/data/webui/history/history_app_test.ts
@@ -113,4 +113,51 @@ assertEquals(1, removeVisitsArg[0].timestamps.length); assertEquals(1000, removeVisitsArg[0].timestamps[0]); }); + + test('ChangesQueryStateWithFilterChips', async () => { + const filterChips = element.shadowRoot!.querySelector( + 'cr-history-embeddings-filter-chips')!; + const changeQueryEventPromise = eventToPromise('change-query', element); + filterChips.dispatchEvent(new CustomEvent('selected-suggestion-changed', { + detail: { + value: { + timeRangeStart: new Date('2011-01-01'), + }, + }, + composed: true, + bubbles: true, + })); + const changeQueryEvent = await changeQueryEventPromise; + assertEquals('', changeQueryEvent.detail.search); + assertEquals('2011-01-01', changeQueryEvent.detail.after); + }); + + test('UpdatesBindingsOnChangeQuery', async () => { + // Change query to a multi-word search term and an after date. + element.dispatchEvent(new CustomEvent('change-query', { + bubbles: true, + composed: true, + detail: { + search: 'two words', + after: '2022-04-02', + }, + })); + await flushTasks(); + + const expectedDateObject = new Date('2022-04-02'); + expectedDateObject.setHours(0, 0, 0, 0); + + const filterChips = element.shadowRoot!.querySelector( + 'cr-history-embeddings-filter-chips')!; + assertTrue(!!filterChips); + assertEquals( + expectedDateObject.getTime(), filterChips.timeRangeStart?.getTime()); + + const historyEmbeddings = + element.shadowRoot!.querySelector('cr-history-embeddings'); + assertTrue(!!historyEmbeddings); + assertEquals( + expectedDateObject.getTime(), + historyEmbeddings.timeRangeStart?.getTime()); + }); });
diff --git a/chrome/test/data/webui/history/history_routing_test.ts b/chrome/test/data/webui/history/history_routing_test.ts index f69f8f2b..a1f3593 100644 --- a/chrome/test/data/webui/history/history_routing_test.ts +++ b/chrome/test/data/webui/history/history_routing_test.ts
@@ -187,17 +187,18 @@ assertEquals( 'chrome://history/?q=' + searchTerm, window.location.href); - if (isHistoryClustersEnabled) { - const tabs = app.shadowRoot!.querySelector('cr-tabs'); - assertTrue(!!tabs); - tabs.selected = 1; - await tabs.updateComplete; - assertEquals('grouped', sidebar.$.menu.selected); - assertEquals(searchTerm, app.$.toolbar.searchTerm); - assertEquals( - 'chrome://history/grouped?q=' + searchTerm, window.location.href); - } - }); + if (isHistoryClustersEnabled) { + const tabs = app.shadowRoot!.querySelector('cr-tabs'); + assertTrue(!!tabs); + tabs.selected = 1; + await tabs.updateComplete; + assertEquals('grouped', sidebar.$.menu.selected); + assertEquals(searchTerm, app.$.toolbar.searchTerm); + assertEquals( + 'chrome://history/grouped?q=' + searchTerm, + window.location.href); + } + }); }); }); @@ -288,7 +289,7 @@ return flushTasks(); }); - test('route updates from filter chips', () => { + test('route updates from group filter chip', () => { // Tabs should be hidden. assertEquals(null, app.shadowRoot!.querySelector('cr-tabs')); @@ -306,4 +307,58 @@ 'show-results-by-group-changed', {detail: {value: false}})); assertEquals('chrome://history/', window.location.href); }); + + test('route updates from date filter chip', () => { + navigateTo('/?q=test', app); + + const filterChips = + app.shadowRoot!.querySelector('cr-history-embeddings-filter-chips'); + assertTrue(!!filterChips); + + // Changing the "By group" chip to should change the URL. + filterChips.dispatchEvent(new CustomEvent('selected-suggestion-changed', { + detail: { + value: { + timeRangeStart: new Date('2011-01-01'), + }, + }, + composed: true, + bubbles: true, + })); + assertEquals( + 'chrome://history/?q=test&after=2011-01-01', window.location.href); + }); + + test('route clears date if invalid', () => { + navigateTo('/?q=test&after=2022-invalid-date', app); + assertEquals('chrome://history/?q=test', window.location.href); + }); + + test('route sets correct date', () => { + navigateTo('/?q=test&after=2022-12-04', app); + + function stringAsDateObject(dateString: string) { + const dateObject = new Date(dateString); + dateObject.setHours(0, 0, 0, 0); + return dateObject; + } + + const expectedDateObject = new Date('2022-12-04'); + expectedDateObject.setHours(0, 0, 0, 0); + + const filterChips = + app.shadowRoot!.querySelector('cr-history-embeddings-filter-chips'); + assertTrue(!!filterChips); + assertEquals( + stringAsDateObject('2022-12-04').getTime(), + filterChips.timeRangeStart?.getTime()); + + navigateTo('/?q=test&after=1999-01-30', app); + assertEquals( + stringAsDateObject('1999-01-30').getTime(), + filterChips.timeRangeStart?.getTime()); + + navigateTo('/?q=test', app); + assertEquals(undefined, filterChips.timeRangeStart); + }); });
diff --git a/chrome/test/data/webui/new_tab_page/modules/v2/calendar/module_test.ts b/chrome/test/data/webui/new_tab_page/modules/v2/calendar/module_test.ts index c9eea30..fce544e 100644 --- a/chrome/test/data/webui/new_tab_page/modules/v2/calendar/module_test.ts +++ b/chrome/test/data/webui/new_tab_page/modules/v2/calendar/module_test.ts
@@ -4,6 +4,7 @@ import type {CalendarModuleElement} from 'chrome://new-tab-page/lazy_load.js'; import {googleCalendarDescriptor, outlookCalendarDescriptor} from 'chrome://new-tab-page/lazy_load.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {isVisible} from 'chrome://webui-test/test_util.js'; @@ -13,29 +14,22 @@ document.body.innerHTML = window.trustedTypes!.emptyHTML; }); - test('creates google calendar module', async () => { - const module = - await googleCalendarDescriptor.initialize(0) as CalendarModuleElement; - assertTrue(!!module); - document.body.append(module); - await waitAfterNextRender(module); + [ + {descriptor: googleCalendarDescriptor, title: 'Google Calendar'}, + {descriptor: outlookCalendarDescriptor, title: 'Outlook Calendar'}, + ].forEach(({descriptor, title}) => { + test(`creates ${title} module`, async () => { + loadTimeData.overrideValues({ + modulesGoogleCalendarTitle: title, + }); + const module = await descriptor.initialize(0) as CalendarModuleElement; + assertTrue(!!module); + document.body.append(module); + await waitAfterNextRender(module); - // Assert. - assertTrue( - isVisible(module.shadowRoot!.querySelector('ntp-module-header-v2'))); - assertEquals(module.shadowRoot!.querySelector('p')!.innerText, '0'); - }); - - test('creates outlook calendar module', async () => { - const module = - await outlookCalendarDescriptor.initialize(0) as CalendarModuleElement; - assertTrue(!!module); - document.body.append(module); - await waitAfterNextRender(module); - - // Assert. - assertTrue( - isVisible(module.shadowRoot!.querySelector('ntp-module-header-v2'))); - assertEquals(module.shadowRoot!.querySelector('p')!.innerText, '1'); + // Assert. + assertTrue(isVisible(module.$.moduleHeaderElementV2)); + assertEquals(module.$.moduleHeaderElementV2.headerText, title); + }); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page/internet_page_test.ts b/chrome/test/data/webui/settings/chromeos/internet_page/internet_page_test.ts index 135eb6b..89ee58fb 100644 --- a/chrome/test/data/webui/settings/chromeos/internet_page/internet_page_test.ts +++ b/chrome/test/data/webui/settings/chromeos/internet_page/internet_page_test.ts
@@ -15,6 +15,7 @@ import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js'; +import {assert} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {ApnProperties, DeviceStateProperties, GlobalPolicy, InhibitReason, MAX_NUM_CUSTOM_APNS, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {ConnectionStateType, DeviceStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; @@ -1153,6 +1154,48 @@ assertNull(getDiscoverMoreApnsTooltip()); }); + [true, false].forEach(isApnPoliciesEnabled => { + test( + `Managed APN UI states when isApnPoliciesEnabled is ${ + isApnPoliciesEnabled}`, + async () => { + loadTimeData.overrideValues({ + isApnRevampEnabled: true, + isApnPoliciesEnabled: isApnPoliciesEnabled, + }); + await navigateToApnSubpage(); + + mojoApi.setGlobalPolicy(undefined); + await flushTasks(); + + // Check for APN policies managed icon. + const getApnManagedIcon = () => + internetPage.shadowRoot!.querySelector('#apnManagedIcon'); + const apnActionMenuButton = + internetPage.shadowRoot!.querySelector<HTMLButtonElement>( + '#apnActionMenuButton'); + assertFalse(!!getApnManagedIcon()); + assert(apnActionMenuButton); + assertFalse(apnActionMenuButton.disabled); + + let globalPolicy = { + allowApnModification: true, + } as GlobalPolicy; + mojoApi.setGlobalPolicy(globalPolicy); + await flushTasks(); + assertFalse(!!getApnManagedIcon()); + assertFalse(apnActionMenuButton.disabled); + + globalPolicy = { + allowApnModification: false, + } as GlobalPolicy; + mojoApi.setGlobalPolicy(globalPolicy); + await flushTasks(); + assertEquals(isApnPoliciesEnabled, !!getApnManagedIcon()); + assertEquals(isApnPoliciesEnabled, apnActionMenuButton.disabled); + }); + }); + test('Navigate to Passpoint detail page', async () => { const subId = 'a_passpoint_id'; const sub = {
diff --git a/chrome/test/data/webui/settings/chromeos/os_a11y_page/keyboard_and_text_input_page_test.ts b/chrome/test/data/webui/settings/chromeos/os_a11y_page/keyboard_and_text_input_page_test.ts index ebceb03..14f0656 100644 --- a/chrome/test/data/webui/settings/chromeos/os_a11y_page/keyboard_and_text_input_page_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_a11y_page/keyboard_and_text_input_page_test.ts
@@ -5,14 +5,15 @@ import 'chrome://os-settings/lazy_load.js'; import {SettingsKeyboardAndTextInputPageElement} from 'chrome://os-settings/lazy_load.js'; -import {CrLinkRowElement, CrSettingsPrefs, Router, routes, SettingsDropdownMenuElement, SettingsPrefsElement, SettingsToggleButtonElement} from 'chrome://os-settings/os_settings.js'; +import {CrLinkRowElement, CrSettingsPrefs, Router, routes, SettingsPrefsElement, SettingsSliderElement, SettingsToggleButtonElement} from 'chrome://os-settings/os_settings.js'; import {assert} from 'chrome://resources/js/assert.js'; import {webUIListenerCallback} from 'chrome://resources/js/cr.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.js'; +import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertNotEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; suite('<settings-keyboard-and-text-input-page>', () => { @@ -221,22 +222,44 @@ assert(caretBlinkIntervalRow); assertTrue(isVisible(caretBlinkIntervalRow)); - const caretBlinkIntervalMenu = - page.shadowRoot!.querySelector<SettingsDropdownMenuElement>( - '#caretBlinkIntervalMenu'); - assert(caretBlinkIntervalMenu); - assertTrue(isVisible(caretBlinkIntervalMenu)); + const caretBlinkIntervalSlider = + page.shadowRoot!.querySelector<SettingsSliderElement>( + '#caretBlinkIntervalSlider'); + assert(caretBlinkIntervalSlider); + assertTrue(isVisible(caretBlinkIntervalSlider)); - // Check the default value is what is expected. - const selectElement = - caretBlinkIntervalMenu.shadowRoot!.querySelector('select'); - assert(selectElement); - assertEquals(String(500), selectElement.value); - selectElement.value = String(0); - selectElement.dispatchEvent(new CustomEvent('change')); + // Check the default synthetic pref value is what is expected. + assertEquals(100, caretBlinkIntervalSlider.pref.value); + // Check the actual default interval is what is expected. + assertEquals(500, page.prefs.settings.a11y.caret.blink_interval.value); - const newInterval = page.prefs.settings.a11y.caret.blink_interval.value; - assertEquals(newInterval, 0); + const slider = + caretBlinkIntervalSlider.shadowRoot!.querySelector('cr-slider'); + assert(slider); + + // Make the repeat interval shorter (increase the slider value). + pressAndReleaseKeyOn(slider, 39, [], 'ArrowRight'); + await flushTasks(); + + assertEquals(110, caretBlinkIntervalSlider.pref.value); + assertEquals(455, page.prefs.settings.a11y.caret.blink_interval.value); + + pressAndReleaseKeyOn(slider, 39, [], 'ArrowRight'); + await flushTasks(); + + assertEquals(120, caretBlinkIntervalSlider.pref.value); + assertEquals(417, page.prefs.settings.a11y.caret.blink_interval.value); + + // Now use the left arrow to get the minimum value, which should be "don't + // blink", aka 0. + + while (caretBlinkIntervalSlider.pref.value > 40) { + pressAndReleaseKeyOn(slider, 37, [], 'ArrowLeft'); + await flushTasks(); + } + + assertEquals(40, caretBlinkIntervalSlider.pref.value); + assertEquals(0, page.prefs.settings.a11y.caret.blink_interval.value); }); const selectorRouteList = [
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc index 143f2a0..a55cb0fed 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.cc
@@ -46,6 +46,8 @@ ash::features::kEnableHostnameSetting}; }; +/* Start Test Classes */ + // This class parameterizes the tests to run once with // OSSettingsRevampWayfinding feature enabled and once disabled. class OSSettingsRevampMochaTest : public OSSettingsMochaTest, @@ -136,9 +138,10 @@ crostini::FakeCrostiniFeatures fake_crostini_features_; }; -class OSSettingsMochaTestReducedAnimationsEnabled : public OSSettingsMochaTest { +class OSSettingsRevampMochaTestReducedAnimationsEnabled + : public OSSettingsRevampMochaTest { protected: - OSSettingsMochaTestReducedAnimationsEnabled() { + OSSettingsRevampMochaTestReducedAnimationsEnabled() { scoped_feature_list_.InitAndEnableFeature( ::features::kAccessibilityReducedAnimations); } @@ -147,6 +150,12 @@ base::test::ScopedFeatureList scoped_feature_list_; }; +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampMochaTestReducedAnimationsEnabled, + testing::Bool(), + OSSettingsRevampMochaTestReducedAnimationsEnabled::DescribeParams); + class OSSettingsMochaTestMagnifierFollowsStsEnabled : public OSSettingsMochaTest { protected: @@ -159,9 +168,10 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -class OSSettingsMochaTestMouseKeysEnabled : public OSSettingsMochaTest { +class OSSettingsRevampMochaTestMouseKeysEnabled + : public OSSettingsRevampMochaTest { protected: - OSSettingsMochaTestMouseKeysEnabled() { + OSSettingsRevampMochaTestMouseKeysEnabled() { scoped_feature_list_.InitAndEnableFeature( ::features::kAccessibilityMouseKeys); } @@ -170,9 +180,16 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -class OSSettingsMochaTestCaretBlinkSettingEnabled : public OSSettingsMochaTest { +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampMochaTestMouseKeysEnabled, + testing::Bool(), + OSSettingsRevampMochaTestMouseKeysEnabled::DescribeParams); + +class OSSettingsRevampMochaTestCaretBlinkSettingEnabled + : public OSSettingsRevampMochaTest { protected: - OSSettingsMochaTestCaretBlinkSettingEnabled() { + OSSettingsRevampMochaTestCaretBlinkSettingEnabled() { scoped_feature_list_.InitAndEnableFeature( ::features::kAccessibilityCaretBlinkIntervalSetting); } @@ -181,6 +198,12 @@ base::test::ScopedFeatureList scoped_feature_list_; }; +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampMochaTestCaretBlinkSettingEnabled, + testing::Bool(), + OSSettingsRevampMochaTestCaretBlinkSettingEnabled::DescribeParams); + class OSSettingsMochaTestLacrosOnlyEnabled : public LacrosOnlyMochaBrowserTest { protected: OSSettingsMochaTestLacrosOnlyEnabled() : LacrosOnlyMochaBrowserTest() { @@ -363,6 +386,128 @@ testing::Bool(), OSSettingsRevampDeviceTestAltAndSplitAndBacklightEnabled::DescribeParams); +class OSSettingsRevampMochaTestApnAndHotspotAndPasspointEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampMochaTestApnAndHotspotAndPasspointEnabled() { + scoped_feature_list_.InitWithFeatures( + /*enabled=*/ + { + ash::features::kApnRevamp, + ash::features::kHotspot, + ash::features::kPasspointSettings, + }, + /*disabled=*/{}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampMochaTestApnAndHotspotAndPasspointEnabled, + testing::Bool(), + OSSettingsRevampMochaTestApnAndHotspotAndPasspointEnabled::DescribeParams); + +class OSSettingsRevampInternetTestHotspotEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampInternetTestHotspotEnabled() { + scoped_feature_list_.InitAndEnableFeature(ash::features::kHotspot); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampInternetTestHotspotEnabled, + testing::Bool(), + OSSettingsRevampInternetTestHotspotEnabled::DescribeParams); + +class OSSettingsRevampInternetTestApnAndPasspointEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampInternetTestApnAndPasspointEnabled() { + scoped_feature_list_.InitWithFeatures( + /*enabled=*/ + { + ash::features::kApnRevamp, + ash::features::kPasspointSettings, + }, + /*disabled=*/{}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampInternetTestApnAndPasspointEnabled, + testing::Bool(), + OSSettingsRevampInternetTestApnAndPasspointEnabled::DescribeParams); + +class OSSettingsRevampInternetTestPasspointEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampInternetTestPasspointEnabled() { + scoped_feature_list_.InitWithFeatures( + /*enabled=*/ + { + ash::features::kPasspointSettings, + }, + /*disabled=*/{}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampInternetTestPasspointEnabled, + testing::Bool(), + OSSettingsRevampInternetTestPasspointEnabled::DescribeParams); + +class OSSettingsRevampNearbyShareTestSharingEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampNearbyShareTestSharingEnabled() { + scoped_feature_list_.InitAndEnableFeature(::features::kNearbySharing); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampNearbyShareTestSharingEnabled, + testing::Bool(), + OSSettingsRevampNearbyShareTestSharingEnabled::DescribeParams); + +class OSSettingsRevampOsA11yTestPdfOcrEnabled + : public OSSettingsRevampMochaTest { + protected: + OSSettingsRevampOsA11yTestPdfOcrEnabled() { + scoped_feature_list_.InitAndEnableFeature(::features::kPdfOcr); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P( + RevampParameterized, + OSSettingsRevampOsA11yTestPdfOcrEnabled, + testing::Bool(), + OSSettingsRevampOsA11yTestPdfOcrEnabled::DescribeParams); + +/* End Test Classes */ + IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, AppLanguageSelectionDialog) { RunSettingsTest( "common/app_language_selection_dialog/" @@ -657,6 +802,14 @@ RunSettingsTest("device_page/stylus_test.js"); } +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, GuestOsSharedPaths) { + RunSettingsTest("guest_os/guest_os_shared_paths_test.js"); +} + +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, GuestOsSharedUsbDevices) { + RunSettingsTest("guest_os/guest_os_shared_usb_devices_test.js"); +} + IN_PROC_BROWSER_TEST_P(OSSettingsMochaTestApnRevamp, InternetPageApnSubpage) { RunSettingsTest("internet_page/apn_subpage_test.js"); } @@ -665,26 +818,9 @@ RunSettingsTest("internet_page/apn_detail_dialog_test.js"); } -class OSSettingsMochaTestApnAndHotspotAndPasspointEnabled - : public OSSettingsMochaTest { - protected: - OSSettingsMochaTestApnAndHotspotAndPasspointEnabled() { - scoped_feature_list_.InitWithFeatures( - /*enabled=*/ - { - ash::features::kApnRevamp, - ash::features::kHotspot, - ash::features::kPasspointSettings, - }, - /*disabled=*/{}); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestApnAndHotspotAndPasspointEnabled, - InternetPage) { +IN_PROC_BROWSER_TEST_P( + OSSettingsRevampMochaTestApnAndHotspotAndPasspointEnabled, + InternetPage) { RunSettingsTest("internet_page/internet_page_test.js"); } @@ -698,188 +834,141 @@ RunSettingsTest("internet_page/cellular_roaming_toggle_button_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageCellularSetupDialog) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageCellularSetupDialog) { RunSettingsTest("internet_page/cellular_setup_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageEsimRemoveProfileDialog) { RunSettingsTest("internet_page/esim_remove_profile_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, GuestOsSharedPaths) { - RunSettingsTest("guest_os/guest_os_shared_paths_test.js"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, GuestOsSharedUsbDevices) { - RunSettingsTest("guest_os/guest_os_shared_usb_devices_test.js"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageEsimInstallErrorDialog) { RunSettingsTest("internet_page/esim_install_error_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageEsimRenameDialog) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageEsimRenameDialog) { RunSettingsTest("internet_page/esim_rename_dialog_test.js"); } -class OSSettingsInternetTestHotspotEnabled : public OSSettingsMochaTest { - protected: - OSSettingsInternetTestHotspotEnabled() { - scoped_feature_list_.InitAndEnableFeature(ash::features::kHotspot); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestHotspotEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestHotspotEnabled, InternetPageHotspotConfigDialog) { RunSettingsTest("internet_page/hotspot_config_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestHotspotEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestHotspotEnabled, InternetPageHotspotSubpage) { RunSettingsTest("internet_page/hotspot_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestHotspotEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestHotspotEnabled, InternetPageHotspotSummaryItem) { RunSettingsTest("internet_page/hotspot_summary_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageInternetConfig) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageInternetConfig) { RunSettingsTest("internet_page/internet_config_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageInternetDetailMenu) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageInternetDetailMenu) { RunSettingsTest("internet_page/internet_detail_menu_test.js"); } -class OSSettingsInternetTestApnAndPasspointEnabled - : public OSSettingsMochaTest { - protected: - OSSettingsInternetTestApnAndPasspointEnabled() { - scoped_feature_list_.InitWithFeatures( - /*enabled=*/ - { - ash::features::kApnRevamp, - ash::features::kPasspointSettings, - }, - /*disabled=*/{}); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestApnAndPasspointEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestApnAndPasspointEnabled, InternetPageInternetDetailSubpage) { RunSettingsTest("internet_page/internet_detail_subpage_test.js"); } -class OSSettingsInternetTestPasspointEnabled : public OSSettingsMochaTest { - protected: - OSSettingsInternetTestPasspointEnabled() { - scoped_feature_list_.InitWithFeatures( - /*enabled=*/ - { - ash::features::kPasspointSettings, - }, - /*disabled=*/{}); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestPasspointEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestPasspointEnabled, InternetPageInternetKnownNetworksSubpage) { RunSettingsTest("internet_page/internet_known_networks_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageInternetSubpageMenu) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageInternetSubpageMenu) { RunSettingsTest("internet_page/internet_subpage_menu_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageInternetSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageInternetSubpage) { RunSettingsTest("internet_page/internet_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageNetworkAlwaysOnVpn) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageNetworkAlwaysOnVpn) { RunSettingsTest("internet_page/network_always_on_vpn_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageNetworkDeviceInfoDialog) { RunSettingsTest("internet_page/network_device_info_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageNetworkProxySection) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageNetworkProxySection) { RunSettingsTest("internet_page/network_proxy_section_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageNetworkSummary) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageNetworkSummary) { RunSettingsTest("internet_page/network_summary_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, InternetPageNetworkSummaryItem) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + InternetPageNetworkSummaryItem) { RunSettingsTest("internet_page/network_summary_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestPasspointEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestPasspointEnabled, InternetPagePasspointSubpage) { RunSettingsTest("internet_page/passpoint_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsInternetTestPasspointEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampInternetTestPasspointEnabled, InternetPagePasspointRemoveDialog) { RunSettingsTest("internet_page/passpoint_remove_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageSettingsTrafficCounters) { RunSettingsTest("internet_page/settings_traffic_counters_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, InternetPageTetherConnectionDialog) { RunSettingsTest("internet_page/tether_connection_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, KerberosPage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, KerberosPage) { RunSettingsTest("kerberos_page/kerberos_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, KerberosPageKerberosAccountsSubpage) { RunSettingsTest("kerberos_page/kerberos_accounts_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, KerberosPageKerberosAddAccountDialog) { RunSettingsTest("kerberos_page/kerberos_add_account_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, KeyboardShortcutBanner) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, KeyboardShortcutBanner) { RunSettingsTest("keyboard_shortcut_banner/keyboard_shortcut_banner_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, LockScreenSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, LockScreenSubpage) { RunSettingsTest("lock_screen_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampDisabled, MainPageContainer) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MainPageContainer) { RunSettingsTest("main_page_container/main_page_container_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampEnabled, - MainPageContainerRevamp) { - RunSettingsTest("main_page_container/main_page_container_test.js"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, MainPageContainerPageDisplayer) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + MainPageContainerPageDisplayer) { RunSettingsTest("main_page_container/page_displayer_test.js"); } @@ -888,157 +977,135 @@ RunSettingsTest("main_page_container/route_navigation_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampDisabled, MultidevicePage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePage) { RunSettingsTest("multidevice_page/multidevice_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampEnabled, - MultidevicePageRevamp) { - RunSettingsTest("multidevice_page/multidevice_page_test.js"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceFeatureItem) { RunSettingsTest("multidevice_page/multidevice_feature_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceFeatureToggle) { RunSettingsTest("multidevice_page/multidevice_feature_toggle_test.js"); } -IN_PROC_BROWSER_TEST_F( - OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P( + OSSettingsRevampMochaTest, MultidevicePageMultideviceNotificationAccessSetupDialog) { RunSettingsTest( "multidevice_page/multidevice_notification_access_setup_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultidevicePermissionsSetupDialog) { RunSettingsTest( "multidevice_page/multidevice_permissions_setup_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceSmartlockItem) { RunSettingsTest("multidevice_page/multidevice_smartlock_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, MultidevicePageMultideviceSubPage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + MultidevicePageMultideviceSubPage) { RunSettingsTest("multidevice_page/multidevice_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultiDevicePageMultideviceCombinedSetupItem) { RunSettingsTest("multidevice_page/multidevice_combined_setup_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceTaskContinuationDisabledLink) { RunSettingsTest( "multidevice_page/multidevice_task_continuation_disabled_link_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceTaskContinuationItem) { RunSettingsTest( "multidevice_page/multidevice_task_continuation_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceWifiSyncDisabledLink) { RunSettingsTest( "multidevice_page/multidevice_wifi_sync_disabled_link_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, MultidevicePageMultideviceWifiSyncItem) { RunSettingsTest("multidevice_page/multidevice_wifi_sync_item_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, NearbySharePageNearbyShareConfirmPage) { RunSettingsTest("nearby_share_page/nearby_share_confirm_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, NearbySharePageNearbyShareHighVisibilityPage) { RunSettingsTest( "nearby_share_page/nearby_share_high_visibility_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, NearbySharePageNearbyShareReceiveDialog) { RunSettingsTest("nearby_share_page/nearby_share_receive_dialog_test.js"); } -class OSSettingsNearbyShareTestSharingEnabled : public OSSettingsMochaTest { - protected: - OSSettingsNearbyShareTestSharingEnabled() { - scoped_feature_list_.InitAndEnableFeature(::features::kNearbySharing); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsNearbyShareTestSharingEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampNearbyShareTestSharingEnabled, NearbySharePageNearbyShareSubpage) { RunSettingsTest("nearby_share_page/nearby_share_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OncMojoTest) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OncMojoTest) { RunSettingsTest("onc_mojo_test.js"); } -class OSSettingsOsA11yTestPdfOcrEnabled : public OSSettingsMochaTest { - protected: - OSSettingsOsA11yTestPdfOcrEnabled() { - scoped_feature_list_.InitAndEnableFeature(::features::kPdfOcr); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(OSSettingsOsA11yTestPdfOcrEnabled, OsA11yPage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampOsA11yTestPdfOcrEnabled, OsA11yPage) { RunSettingsTest("os_a11y_page/os_a11y_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsOsA11yTestPdfOcrEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampOsA11yTestPdfOcrEnabled, OsA11yPageLiveCaptionSection) { RunSettingsTest("os_a11y_page/live_caption_section_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageAudioAndCaptionsPage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + OsA11yPageAudioAndCaptionsPage) { RunSettingsTest("os_a11y_page/audio_and_captions_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageChromeVoxSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageChromeVoxSubpage) { RunSettingsTest("os_a11y_page/chromevox_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageCursorAndTouchpadPage) { - RunSettingsTest("os_a11y_page/cursor_and_touchpad_page_test.js"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestMouseKeysEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageCursorAndTouchpadPage) { RunSettingsTest("os_a11y_page/cursor_and_touchpad_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTestMouseKeysEnabled, + OsA11yPageCursorAndTouchpadPage) { + RunSettingsTest("os_a11y_page/cursor_and_touchpad_page_test.js"); +} + +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageChangeDictationLocaleDialog) { RunSettingsTest("os_a11y_page/change_dictation_locale_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageDisplayAndMagnificationSubpage) { RunSettingsTest("os_a11y_page/display_and_magnification_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestReducedAnimationsEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTestReducedAnimationsEnabled, OsA11yPageDisplayAndMagnificationSubpage) { RunSettingsTest("os_a11y_page/display_and_magnification_subpage_test.js"); } @@ -1048,89 +1115,79 @@ RunSettingsTest("os_a11y_page/display_and_magnification_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageKeyboardAndTextInputPage) { RunSettingsTest("os_a11y_page/keyboard_and_text_input_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestCaretBlinkSettingEnabled, - OsA11yPageKeyboardAndTextInputPage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTestCaretBlinkSettingEnabled, + OsA11yPageKeyboardAndTextInputPageCaret) { RunSettingsTest("os_a11y_page/keyboard_and_text_input_page_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageKioskMode) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageKioskMode) { RunSettingsTest("os_a11y_page/os_a11y_page_kiosk_mode_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageSelectToSpeakSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + OsA11yPageSelectToSpeakSubpage) { RunSettingsTest("os_a11y_page/select_to_speak_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageSwitchAccessActionAssignmentDialog) { RunSettingsTest( "os_a11y_page/switch_access_action_assignment_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageSwitchAccessSetupGuideDialog) { RunSettingsTest("os_a11y_page/switch_access_setup_guide_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageSwitchAccessSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + OsA11yPageSwitchAccessSubpage) { RunSettingsTest("os_a11y_page/switch_access_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsOsA11yTestPdfOcrEnabled, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampOsA11yTestPdfOcrEnabled, OsA11yPageTextToSpeechSubpage) { RunSettingsTest("os_a11y_page/text_to_speech_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsA11yPageTtsVoiceSubpage) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsA11yPageTtsVoiceSubpage) { RunSettingsTest("os_a11y_page/tts_voice_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampEnabled, - OsAboutPage_AllBuilds) { - RunSettingsTest("os_about_page/os_about_page_test.js", - "runMochaSuite('<os-about-page> AllBuilds')"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampDisabled, - OsAboutPage_AllBuilds) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsAboutPage_AllBuilds) { RunSettingsTest("os_about_page/os_about_page_test.js", "runMochaSuite('<os-about-page> AllBuilds')"); } #if BUILDFLAG(GOOGLE_CHROME_BRANDING) -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampEnabled, - OsAboutPage_OfficialBuild) { - RunSettingsTest("os_about_page/os_about_page_test.js", - "runMochaSuite('<os-about-page> OfficialBuild')"); -} - -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTestRevampDisabled, - OsAboutPage_OfficialBuild) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsAboutPage_OfficialBuild) { RunSettingsTest("os_about_page/os_about_page_test.js", "runMochaSuite('<os-about-page> OfficialBuild')"); } #endif -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsAboutPageChannelSwitcherDialog) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + OsAboutPageChannelSwitcherDialog) { RunSettingsTest("os_about_page/channel_switcher_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsAboutPageConsumerAutoUpdateToggleDialog) { RunSettingsTest("os_about_page/consumer_auto_update_toggle_dialog_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, OsAboutPageDetailedBuildInfoSubpage) { RunSettingsTest("os_about_page/detailed_build_info_subpage_test.js"); } -IN_PROC_BROWSER_TEST_F(OSSettingsMochaTest, OsAboutPageEditHostnameDialog) { +IN_PROC_BROWSER_TEST_P(OSSettingsRevampMochaTest, + OsAboutPageEditHostnameDialog) { RunSettingsTest("os_about_page/edit_hostname_dialog_test.js"); }
diff --git a/chrome/test/data/webui/side_panel/read_anything/BUILD.gn b/chrome/test/data/webui/side_panel/read_anything/BUILD.gn index 6bd4494..13fad440 100644 --- a/chrome/test/data/webui/side_panel/read_anything/BUILD.gn +++ b/chrome/test/data/webui/side_panel/read_anything/BUILD.gn
@@ -28,8 +28,10 @@ "highlight_toggle_test.ts", "app_receives_toolbar_changes_test.ts", "test_color_updater_browser_proxy.ts", + "language_menu_test.ts", "links_toggled_integration.ts", "common.ts", + "voice_language_util_test.ts", "read_aloud_update_content_selection.ts", "read_aloud_update_content_selection_pdf.ts", "read_aloud_highlighting_test.ts",
diff --git a/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts b/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts index 0147ce1..ee1458d9 100644 --- a/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts
@@ -8,6 +8,7 @@ import {flush} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import type {ReadAnythingElement} from 'chrome-untrusted://read-anything-side-panel.top-chrome/app.js'; import {defaultFontName} from 'chrome-untrusted://read-anything-side-panel.top-chrome/common.js'; +import {LANGUAGE_TOGGLE_EVENT} from 'chrome-untrusted://read-anything-side-panel.top-chrome/language_menu.js'; import {FONT_EVENT, FONT_SIZE_EVENT, HIGHLIGHT_TOGGLE_EVENT, LETTER_SPACING_EVENT, LINE_SPACING_EVENT, NEXT_GRANULARITY_EVENT, PLAY_PAUSE_EVENT, PREVIOUS_GRANULARITY_EVENT, RATE_EVENT, THEME_EVENT} from 'chrome-untrusted://read-anything-side-panel.top-chrome/read_anything_toolbar.js'; import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; @@ -212,6 +213,47 @@ }); }); + suite('on language toggle', () => { + function emitLanguageToggle(lang: string): void { + emitEvent(app, LANGUAGE_TOGGLE_EVENT, {detail: {language: lang}}); + } + + test('enabled languages are added', () => { + const firstLanguage = 'English'; + emitLanguageToggle(firstLanguage); + // Bypass Typescript compiler to allow us to read a private property + // @ts-ignore + assertTrue(app.enabledLanguagesInPref.includes(firstLanguage)); + assertTrue(chrome.readingMode.getLanguagesEnabledInPref() + .includes(firstLanguage)); + + const secondLanguage = 'French'; + emitLanguageToggle(secondLanguage); + // Bypass Typescript compiler to allow us to read a private property + // @ts-ignore + assertTrue(app.enabledLanguagesInPref.includes(secondLanguage)); + assertTrue(chrome.readingMode.getLanguagesEnabledInPref() + .includes(secondLanguage)); + }); + + test('disabled languages are removed', () => { + const firstLanguage = 'English'; + emitLanguageToggle(firstLanguage); + // Bypass Typescript compiler to allow us to read a private property + // @ts-ignore + assertTrue(app.enabledLanguagesInPref.includes(firstLanguage)); + assertTrue(chrome.readingMode.getLanguagesEnabledInPref() + .includes(firstLanguage)); + + emitLanguageToggle(firstLanguage); + // Bypass Typescript compiler to allow us to read a private property + // @ts-ignore + assertFalse(app.enabledLanguagesInPref.includes(firstLanguage)); + assertFalse(chrome.readingMode.getLanguagesEnabledInPref() + .includes(firstLanguage)); + }); + }); + suite('on speech rate change', () => { function emitRate(rate: number): void { emitEvent(app, RATE_EVENT, {detail: {rate}});
diff --git a/chrome/test/data/webui/side_panel/read_anything/fake_reading_mode.ts b/chrome/test/data/webui/side_panel/read_anything/fake_reading_mode.ts index 35ba704..5925792 100644 --- a/chrome/test/data/webui/side_panel/read_anything/fake_reading_mode.ts +++ b/chrome/test/data/webui/side_panel/read_anything/fake_reading_mode.ts
@@ -56,6 +56,9 @@ // The base language code that should be used for speech synthesis voices. baseLanguageForSpeech: string = ''; + // TTS voice language preferences saved in database + savedLanguagePref: Set<string> = new Set<string>(); + private maxNodeId: number = 5; // Returns the stored user voice preference for the current language. @@ -154,6 +157,16 @@ this.fontSize = 0; } + // Called when a user toggles a switch in the language menu + onLanguagePrefChange(lang: string, enabled: boolean) { + if(enabled) { + this.savedLanguagePref.add(lang); + } else { + this.savedLanguagePref.delete(lang); + } + } + + // Called when a user toggles links via the webui toolbar. onLinksEnabledToggled() { this.linksEnabled = !this.linksEnabled; @@ -220,6 +233,11 @@ return letterSpacing; } + // Returns the actual enabled languages in preference + getLanguagesEnabledInPref(): string[] { + return [...this.savedLanguagePref.values()]; + } + // Called when a user makes a selection change. AnchorNodeID and // focusAXNodeID are AXNodeIDs which identify the anchor and focus AXNodes // in the main pane. The selection can either be forward or backwards.
diff --git a/chrome/test/data/webui/side_panel/read_anything/language_menu_test.ts b/chrome/test/data/webui/side_panel/read_anything/language_menu_test.ts new file mode 100644 index 0000000..3e50420fb --- /dev/null +++ b/chrome/test/data/webui/side_panel/read_anything/language_menu_test.ts
@@ -0,0 +1,357 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome-untrusted://read-anything-side-panel.top-chrome/language_menu.js'; + +import type {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.js'; +import type {CrToggleElement} from '//resources/cr_elements/cr_toggle/cr_toggle.js'; +import {flush} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import type {LanguageMenuElement} from 'chrome-untrusted://read-anything-side-panel.top-chrome/language_menu.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; + + +suite('LanguageMenuElement', () => { + let languageMenu: LanguageMenuElement; + let availableVoices: SpeechSynthesisVoice[]; + let enabledLanguagesInPref: string[]; + + + const setAvailableVoices = () => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.availableVoices = availableVoices; + flush(); + }; + + const setEnabledLanguages = () => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.enabledLanguagesInPref = enabledLanguagesInPref; + flush(); + }; + + const getLanguageLineItems = () => { + return languageMenu.$.languageMenu.querySelectorAll<HTMLElement>( + '.language-line'); + }; + + const getLanguageSearchField = () => { + return languageMenu.$.languageMenu.querySelector<CrInputElement>( + '.search-field')!; + }; + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + languageMenu = document.createElement('language-menu'); + document.body.appendChild(languageMenu); + flush(); + }); + + suite('with one language', () => { + setup(() => { + availableVoices = + [{name: 'test voice 1', lang: 'en-US'} as SpeechSynthesisVoice]; + setAvailableVoices(); + languageMenu.showDialog(); + }); + + test( + 'defaults to the locale when there is no display name with a switch', + () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'en-US'); + assertEquals(getLanguageSearchField().value, ''); + }); + + suite('when availableVoices updates', () => { + setup(() => { + availableVoices = [ + {name: 'test voice 1', lang: 'en-US'} as SpeechSynthesisVoice, + {name: 'test voice 2', lang: 'en-UK'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + }); + + test('it updates and displays the new languages', () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 2); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'en-US'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[1]!, 'en-UK'); + assertEquals(getLanguageSearchField().value, ''); + }); + }); + + suite('with display names for locales', () => { + setup(() => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.localeToDisplayName = { + 'en-US': 'English (United States)', + }; + flush(); + }); + + test('it displays the display name', () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English (United States)'); + }); + + suite('with search input', () => { + test('it displays no language without a match', async () => { + getLanguageSearchField().value = 'test'; + await getLanguageSearchField().updateComplete; + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 0); + }); + + test('it displays matching language with a match', async () => { + getLanguageSearchField().value = 'english'; + await getLanguageSearchField().updateComplete; + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English (United States)'); + }); + }); + }); + }); + + suite('with multiple languages', () => { + setup(() => { + availableVoices = [ + {name: 'test voice 0', lang: 'en-US'} as SpeechSynthesisVoice, + {name: 'test voice 1', lang: 'it-IT'} as SpeechSynthesisVoice, + {name: 'test voice 2', lang: 'en-UK'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + enabledLanguagesInPref = ['Italian']; + setEnabledLanguages(); + languageMenu.showDialog(); + }); + + test( + 'defaults to the locale when there is no display name with a switch', + () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 3); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'en-US'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[1]!, 'it-IT'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[2]!, 'en-UK'); + assertEquals(getLanguageSearchField().value, ''); + }); + + suite('with display names for locales', () => { + setup(() => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.localeToDisplayName = { + 'en-US': 'English (United States)', + 'it-IT': 'Italian', + 'en-UK': 'English (United Kingdom)', + }; + flush(); + }); + + test('it displays the display name', () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 3); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English (United States)'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[1]!, 'Italian'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[2]!, 'English (United Kingdom)'); + assertEquals(getLanguageSearchField().value, ''); + }); + + test('it does not groups languages with different name', () => { + availableVoices = [ + {name: 'test voice 0', lang: 'en-US'} as SpeechSynthesisVoice, + {name: 'test voice 3', lang: 'en'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.localeToDisplayName = { + 'en-US': 'English (United States)', + 'en': 'English', + }; + flush(); + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 2); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English (United States)'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[1]!, 'English'); + }); + + test('it groups languages with same name', () => { + availableVoices = [ + {name: 'test voice 0', lang: 'en-unknown'} as SpeechSynthesisVoice, + {name: 'test voice 3', lang: 'en'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.localeToDisplayName = { + 'en-unknown': 'English', + 'en': 'English', + }; + flush(); + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English'); + }); + + test('it toggles switch on for initially enabled line', async () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 3); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[0]!, false); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[1]!, true); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[2]!, false); + }); + + test('it toggles switch when language pref changes', async () => { + enabledLanguagesInPref = ['Italian', 'English (United States)']; + setEnabledLanguages(); + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 3); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[0]!, true); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[1]!, true); + assertLanguageLineWithToggleChecked(getLanguageLineItems()[2]!, false); + }); + + suite('with search input', () => { + test('it displays no language without a match', async () => { + getLanguageSearchField().value = 'test'; + await getLanguageSearchField().updateComplete; + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 0); + }); + + test('it displays matching language with a match', async () => { + getLanguageSearchField().value = 'italian'; + await getLanguageSearchField().updateComplete; + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'Italian'); + }); + }); + }); + }); + + suite('with multiple voices for the same language', () => { + setup(() => { + availableVoices = [ + {name: 'test voice 0', lang: 'en-US'} as SpeechSynthesisVoice, + {name: 'test voice 1', lang: 'en-US'} as SpeechSynthesisVoice, + {name: 'test voice 2', lang: 'en-UK'} as SpeechSynthesisVoice, + {name: 'test voice 3', lang: 'en-UK'} as SpeechSynthesisVoice, + {name: 'test voice 4', lang: 'it-IT'} as SpeechSynthesisVoice, + {name: 'test voice 5', lang: 'zh-CN'} as SpeechSynthesisVoice, + ]; + setAvailableVoices(); + languageMenu.showDialog(); + }); + + test('only shows one line per unique language name', () => { + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 4); + assertLanguageLineWithTextAndSwitch(getLanguageLineItems()[0]!, 'en-US'); + assertLanguageLineWithTextAndSwitch(getLanguageLineItems()[1]!, 'en-UK'); + assertLanguageLineWithTextAndSwitch(getLanguageLineItems()[2]!, 'it-IT'); + assertLanguageLineWithTextAndSwitch(getLanguageLineItems()[3]!, 'zh-CN'); + }); + + suite('with display names for locales', () => { + setup(() => { + // Bypass Typescript compiler to allow us to set a private readonly + // property + // @ts-ignore + languageMenu.localeToDisplayName = { + 'en-US': 'English (United States)', + 'it-IT': 'Italian', + 'en-UK': 'English (United Kingdom)', + 'zh-CN': 'Chinese', + }; + flush(); + }); + + test('it displays the display name', () => { + flush(); + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 4); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'English (United States)'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[1]!, 'English (United Kingdom)'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[2]!, 'Italian'); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[3]!, 'Chinese'); + assertEquals(getLanguageSearchField().value, ''); + }); + + suite('with search input', () => { + test('it displays no language without a match', async () => { + getLanguageSearchField().value = 'test'; + await getLanguageSearchField().updateComplete; + assertTrue(isPositionedOnPage(languageMenu)); + assertEquals(getLanguageLineItems().length, 0); + }); + + test('it displays matching language with a match', async () => { + getLanguageSearchField().value = 'chin'; + await getLanguageSearchField().updateComplete; + assertEquals(getLanguageLineItems().length, 1); + assertLanguageLineWithTextAndSwitch( + getLanguageLineItems()[0]!, 'Chinese'); + }); + }); + }); + }); +}); + +function isPositionedOnPage(element: HTMLElement) { + return !!element && + !!(element.offsetWidth || element.offsetHeight || + element.getClientRects().length); +} + +function assertLanguageLineWithTextAndSwitch( + element: HTMLElement, expectedText: string) { + assertEquals(expectedText, element.textContent!.trim()); + assertEquals(2, element.children.length); + assertEquals('CR-TOGGLE', element.children[1]!.tagName); +} + +async function assertLanguageLineWithToggleChecked( + element: HTMLElement, expectedChecked: boolean) { + const toggle: CrToggleElement = (element.querySelector('cr-toggle'))!; + await toggle.updateComplete; + if (expectedChecked) { + assertTrue(toggle.checked); + assertTrue(toggle.hasAttribute('checked')); + assertEquals('true', toggle.getAttribute('aria-pressed')); + } else { + assertFalse(toggle.checked); + assertEquals(null, toggle.getAttribute('checked')); + assertEquals('false', toggle.getAttribute('aria-pressed')); + } +}
diff --git a/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc b/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc index 228c6cfb5..5153278 100644 --- a/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc +++ b/chrome/test/data/webui/side_panel/read_anything/read_anything_browsertest.cc
@@ -48,6 +48,11 @@ "mocha.run()"); } +IN_PROC_BROWSER_TEST_F(ReadAnythingMochaTest, VoiceLanguageUtil) { + RunSidePanelTest("side_panel/read_anything/voice_language_util_test.js", + "mocha.run()"); +} + IN_PROC_BROWSER_TEST_F(ReadAnythingMochaTest, ReadAloudFlag) { RunSidePanelTest("side_panel/read_anything/read_aloud_flag_test.js", "mocha.run()"); @@ -87,6 +92,11 @@ "mocha.run()"); } +IN_PROC_BROWSER_TEST_F(ReadAnythingMochaTest, LanguageMenu) { + RunSidePanelTest("side_panel/read_anything/language_menu_test.js", + "mocha.run()"); +} + IN_PROC_BROWSER_TEST_F(ReadAnythingMochaTest, LinksToggle) { RunSidePanelTest("side_panel/read_anything/links_toggle_button_test.js", "mocha.run()");
diff --git a/chrome/test/data/webui/side_panel/read_anything/voice_language_util_test.ts b/chrome/test/data/webui/side_panel/read_anything/voice_language_util_test.ts new file mode 100644 index 0000000..4f7c1bd --- /dev/null +++ b/chrome/test/data/webui/side_panel/read_anything/voice_language_util_test.ts
@@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_language_util.js'; + +import {mojoVoicePackStatusToVoicePackStatusEnum, VoicePackStatus} from 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_language_util.js'; +import {assertEquals} from 'chrome-untrusted://webui-test/chai_assert.js'; + +suite('voice and language utils', () => { + test('mojoVoicePackStatusToVoicePackStatusEnum', () => { + // Success codes + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kNotInstalled')), + VoicePackStatus.NOT_INSTALLED); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kInstalled')), + VoicePackStatus.INSTALLED); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kInstalling')), + VoicePackStatus.INSTALLING); + + // Error codes + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kUnknown')), + VoicePackStatus.ERROR); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kOther')), + VoicePackStatus.ERROR); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kWrongId')), + VoicePackStatus.ERROR); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kNeedReboot')), + VoicePackStatus.ERROR); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kAllocation')), + VoicePackStatus.ERROR); + assertEquals( + (mojoVoicePackStatusToVoicePackStatusEnum('kUnsupportedPlatform')), + VoicePackStatus.ERROR); + }); +});
diff --git a/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts b/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts index 6a63196..8c2fdf6 100644 --- a/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/voice_selection_menu_test.ts
@@ -6,6 +6,8 @@ import type {CrIconButtonElement} from '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; import {flush} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import type {LanguageMenuElement} from 'chrome-untrusted://read-anything-side-panel.top-chrome/language_menu.js'; +import {PLAY_PREVIEW_EVENT} from 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_selection_menu.js'; import type {VoiceSelectionMenuElement} from 'chrome-untrusted://read-anything-side-panel.top-chrome/voice_selection_menu.js'; import {assertEquals, assertFalse, assertStringContains, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; @@ -18,6 +20,9 @@ let availableVoices: SpeechSynthesisVoice[]; let myClickEvent: MouseEvent; + const voiceSelectionButtonSelector: string = + '.dropdown-voice-selection-button:not(.language-menu-button)'; + const setAvailableVoices = () => { // Bypass Typescript compiler to allow us to set a private readonly // property @@ -71,6 +76,17 @@ availableVoices[0]!.name); }); + test('it shows language menu after button click', () => { + const button = + voiceSelectionMenu!.$.voiceSelectionMenu.get() + .querySelector<HTMLButtonElement>('.language-menu-button'); + button!.click(); + const languageMenuElement: LanguageMenuElement = + voiceSelectionMenu!.$.languageMenu.get(); + assertTrue(isPositionedOnPage(languageMenuElement.$.languageMenu)); + flush(); + }); + suite('when availableVoices updates', () => { setup(() => { availableVoices = [ @@ -87,7 +103,7 @@ const dropdownItems: NodeListOf<HTMLElement> = voiceSelectionMenu!.$.voiceSelectionMenu.get() .querySelectorAll<HTMLButtonElement>( - '.dropdown-voice-selection-button'); + voiceSelectionButtonSelector); assertEquals( getDropdownItemForVoice(availableVoices[0]!).textContent!.trim(), @@ -257,6 +273,30 @@ }); }); + suite('when preview button is clicked', () => { + let clickEmitted: boolean; + + setup(() => { + clickEmitted = false; + document.addEventListener( + PLAY_PREVIEW_EVENT, () => clickEmitted = true); + + // Display dropdown menu + voiceSelectionMenu!.onVoiceSelectionMenuClick(myClickEvent); + flush(); + }); + + test('it emits play preview event', () => { + const previewButton = + getDropdownItemForVoice(availableVoices[0]!) + .querySelector<CrIconButtonElement>('#preview-icon')!; + + previewButton!.click(); + flush(); + assertTrue(clickEmitted); + }); + }); + suite('when preview starts playing', () => { setup(() => { // Display dropdown menu @@ -277,14 +317,14 @@ getDropdownItemForVoice(previewVoice) .querySelector<CrIconButtonElement>('#preview-icon')!; - // The play icon should flip to pause for the voice being previewed + // The play icon should flip to stop for the voice being previewed assertTrue(isPositionedOnPage(playIconOfPreviewVoice)); assertEquals( - playIconOfPreviewVoice.ironIcon, 'read-anything-20:pause-circle'); + playIconOfPreviewVoice.ironIcon, 'read-anything-20:stop-circle'); assertStringContains( - playIconOfPreviewVoice.title.toLowerCase(), 'pause'); + playIconOfPreviewVoice.title.toLowerCase(), 'stop'); assertStringContains( - playIconOfPreviewVoice.ariaLabel!.toLowerCase(), 'pause'); + playIconOfPreviewVoice.ariaLabel!.toLowerCase(), 'stop'); // The play icon should remain unchanged for the other buttons assertTrue(isPositionedOnPage(playIconVoice0)); assertEquals(playIconVoice0.ironIcon, 'read-anything-20:play-circle');
diff --git a/chrome/test/data/webui/side_panel/reading_list/reading_list_app_test.ts b/chrome/test/data/webui/side_panel/reading_list/reading_list_app_test.ts index a91e46d..ed396b81 100644 --- a/chrome/test/data/webui/side_panel/reading_list/reading_list_app_test.ts +++ b/chrome/test/data/webui/side_panel/reading_list/reading_list_app_test.ts
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://read-later.top-chrome/app.js'; +import 'chrome://read-later.top-chrome/reading_list_app.js'; -import type {ReadingListAppElement} from 'chrome://read-later.top-chrome/app.js'; +import type {ReadingListAppElement} from 'chrome://read-later.top-chrome/reading_list_app.js'; import type {ReadLaterEntriesByStatus} from 'chrome://read-later.top-chrome/reading_list.mojom-webui.js'; import {ReadingListApiProxyImpl} from 'chrome://read-later.top-chrome/reading_list_api_proxy.js'; import type {ReadingListItemElement} from 'chrome://read-later.top-chrome/reading_list_item.js';
diff --git a/chrome/updater/cleanup_task.cc b/chrome/updater/cleanup_task.cc index e0578f6..d832ee6 100644 --- a/chrome/updater/cleanup_task.cc +++ b/chrome/updater/cleanup_task.cc
@@ -12,6 +12,7 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/logging.h" +#include "base/memory/scoped_refptr.h" #include "base/process/launch.h" #include "base/process/process.h" #include "base/sequence_checker.h" @@ -19,19 +20,77 @@ #include "base/time/time.h" #include "base/version.h" #include "chrome/updater/app/app_uninstall.h" +#include "chrome/updater/configurator.h" #include "chrome/updater/updater_version.h" #include "chrome/updater/util/util.h" #if BUILDFLAG(IS_WIN) +#include <string> +#include <vector> + +#include "base/strings/sys_string_conversions.h" +#include "base/win/registry.h" +#include "chrome/updater/persisted_data.h" #include "chrome/updater/util/win_util.h" +#include "chrome/updater/win/win_constants.h" #endif namespace updater { - namespace { constexpr int kMilestoneDeletionThreshold = 8; +#if BUILDFLAG(IS_WIN) +// TODO(crbug.com/335673799) - remove the code in M129, after the brand codes +// have been repaired. +void RepairAppBrandCode(UpdaterScope scope, + scoped_refptr<PersistedData> persisted_data) { + const HKEY root = UpdaterScopeToHKeyRoot(scope); + + struct AppBrand { + std::string app_id; + std::string brand; + }; + + // Contains the pairs of {`app_id`, `brand`}, if the `brand` is present. + const std::vector<AppBrand> app_brands = [persisted_data] { + std::vector<AppBrand> app_brands; + for (const std::string& app_id : persisted_data->GetAppIds()) { + const std::string brand = persisted_data->GetBrandCode(app_id); + if (brand.empty()) { + continue; + } + app_brands.emplace_back(app_id, brand); + } + return app_brands; + }(); + + // Updates the brand in registry, if a `brand` is present in prefs and the + // the client state for the `app_id` does not contain a `brand`. + for (const auto& [app_id, brand] : app_brands) { + const std::wstring brand_prefs = base::SysUTF8ToWide(brand); + if (brand_prefs.empty()) { + continue; + } + base::win::RegKey key; + if (key.Open(root, GetAppClientStateKey(app_id).c_str(), + Wow6432(KEY_READ | KEY_WRITE)) != ERROR_SUCCESS) { + continue; + } + std::wstring brand_registry; + key.ReadValue(kRegValueBrandCode, &brand_registry); + if (!brand_registry.empty()) { + continue; + } + VLOG(1) << __func__ << ": missing " << brand_prefs << " for " << app_id; + const LONG res = key.WriteValue(kRegValueBrandCode, brand_prefs.c_str()); + VLOG(1) << __func__ << [&res] { + return res != ERROR_SUCCESS ? ": not repaired " : ": repaired "; + }() << res; + } +} +#endif // IS_WIN + void CleanupGoogleUpdate(UpdaterScope scope) { #if BUILDFLAG(IS_WIN) // Delete anything other than `GoogleUpdate.exe` under `\Google\Update`. @@ -74,13 +133,20 @@ } // namespace -CleanupTask::CleanupTask(UpdaterScope scope) : scope_(scope) {} +CleanupTask::CleanupTask(UpdaterScope scope, scoped_refptr<Configurator> config) + : scope_(scope), config_(config) {} CleanupTask::~CleanupTask() = default; void CleanupTask::Run(base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +#if BUILDFLAG(IS_WIN) + if (config_) { + RepairAppBrandCode(scope_, config_->GetUpdaterPersistedData()); + } +#endif // IS_WIN + base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::WithBaseSyncPrimitives()}, base::BindOnce(
diff --git a/chrome/updater/cleanup_task.h b/chrome/updater/cleanup_task.h index 1865cb9..dd6aac4 100644 --- a/chrome/updater/cleanup_task.h +++ b/chrome/updater/cleanup_task.h
@@ -8,17 +8,20 @@ #include "base/functional/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" #include "chrome/updater/updater_scope.h" namespace updater { +class Configurator; + // The Cleanup houses both periodic and one-time cleanup work items. For // example, it is used to clean up obsolete files that were in-use at the time // setup ran but can be cleaned up now. class CleanupTask : public base::RefCountedThreadSafe<CleanupTask> { public: - explicit CleanupTask(UpdaterScope scope); + CleanupTask(UpdaterScope scope, scoped_refptr<Configurator> config); void Run(base::OnceClosure callback); private: @@ -27,6 +30,7 @@ SEQUENCE_CHECKER(sequence_checker_); UpdaterScope scope_; + scoped_refptr<Configurator> config_; }; } // namespace updater
diff --git a/chrome/updater/cleanup_task_unittest.cc b/chrome/updater/cleanup_task_unittest.cc index 8bc140d6..5f4c856 100644 --- a/chrome/updater/cleanup_task_unittest.cc +++ b/chrome/updater/cleanup_task_unittest.cc
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" #include "base/version.h" +#include "chrome/updater/configurator.h" #include "chrome/updater/test_scope.h" #include "chrome/updater/updater_version.h" #include "chrome/updater/util/unit_test_util.h" @@ -58,7 +59,8 @@ ASSERT_TRUE(folder_path_current); ASSERT_TRUE(base::CreateDirectory(*folder_path_current)); - auto cleanup_task = base::MakeRefCounted<CleanupTask>(GetTestScope()); + auto cleanup_task = + base::MakeRefCounted<CleanupTask>(GetTestScope(), /*config=*/nullptr); base::RunLoop run_loop; cleanup_task->Run(run_loop.QuitClosure()); run_loop.Run();
diff --git a/chrome/updater/update_service_impl_impl.cc b/chrome/updater/update_service_impl_impl.cc index 31d0175..cbd93a5f 100644 --- a/chrome/updater/update_service_impl_impl.cc +++ b/chrome/updater/update_service_impl_impl.cc
@@ -702,7 +702,8 @@ base::MakeRefCounted<AutoRunOnOsUpgradeTask>( GetUpdaterScope(), config_->GetUpdaterPersistedData()))); new_tasks.push_back(base::BindOnce( - &CleanupTask::Run, base::MakeRefCounted<CleanupTask>(GetUpdaterScope()))); + &CleanupTask::Run, + base::MakeRefCounted<CleanupTask>(GetUpdaterScope(), config_))); const auto barrier_closure = base::BarrierClosure(new_tasks.size(), std::move(callback));
diff --git a/chromecast/base/chromecast_switches.cc b/chromecast/base/chromecast_switches.cc index 00d1a187..eb121a6 100644 --- a/chromecast/base/chromecast_switches.cc +++ b/chromecast/base/chromecast_switches.cc
@@ -21,9 +21,15 @@ // Default is "https://clients2.google.com/cr/staging_report" for non prod. const char kCrashServerUrl[] = "crash-server-url"; +// Switch to enable daemon-mode in crash_uploader. +const char kCrashUploaderDaemon[] = "daemon"; + // Switch to disable Crash reporting const char kDisableCrashReporter[] = "disable-crash-reporter"; +// Switch to disable Crashpad forwarding +const char kDisableCrashpadForwarding[] = "disable-crashpad-forwarding"; + // Switch to dumpstate binary path. const char kDumpstateBinPath[] = "dumpstate-path";
diff --git a/chromecast/base/chromecast_switches.h b/chromecast/base/chromecast_switches.h index 5fb6a6b..ee5d4b31 100644 --- a/chromecast/base/chromecast_switches.h +++ b/chromecast/base/chromecast_switches.h
@@ -16,12 +16,16 @@ extern const char kSwitchValueTrue[]; extern const char kSwitchValueFalse[]; -// Url to upload crash data to. +// Switches for crash_uploader extern const char kCrashServerUrl[]; +extern const char kCrashUploaderDaemon[]; // Disable Crash Reporting extern const char kDisableCrashReporter[]; +// Disable Crashpad forwarding +extern const char kDisableCrashpadForwarding[]; + // Path to dumpstate binary to be used for crash reporting. // This gives Chromium's crash reporter the flexibility to switch // between multiple implementations of dumpstate tool.
diff --git a/chromecast/crash/linux/crash_uploader.cc b/chromecast/crash/linux/crash_uploader.cc index ee17634b..aa9ebd11 100644 --- a/chromecast/crash/linux/crash_uploader.cc +++ b/chromecast/crash/linux/crash_uploader.cc
@@ -56,8 +56,12 @@ std::string server_url( command_line->GetSwitchValueASCII(switches::kCrashServerUrl)); + bool daemon = + chromecast::GetSwitchValueBoolean(switches::kCrashUploaderDaemon, false); + LOG_IF(INFO, daemon) << "Running crash uploader in daemon-mode"; + chromecast::MinidumpUploader uploader(sys_info.get(), server_url); - while (true) { + do { if (!uploader.UploadAllMinidumps()) LOG(ERROR) << "Failed to process minidumps"; @@ -65,8 +69,10 @@ chromecast::RebootUtil::RebootNow( chromecast::RebootShlib::CRASH_UPLOADER); - base::PlatformThread::Sleep(base::Seconds(kUploadRetryIntervalDefault)); - } + if (daemon) { + base::PlatformThread::Sleep(base::Seconds(kUploadRetryIntervalDefault)); + } + } while (daemon); return EXIT_SUCCESS; }
diff --git a/chromecast/crash/linux/dump_info.cc b/chromecast/crash/linux/dump_info.cc index c17d3e7..29925891 100644 --- a/chromecast/crash/linux/dump_info.cc +++ b/chromecast/crash/linux/dump_info.cc
@@ -40,6 +40,14 @@ const char kSignatureKey[] = "signature"; const char kExtraInfoKey[] = "extra_info"; +// CastLite specific data +const char kComments[] = "comments"; +const char kJsEngine[] = "js_engine"; +const char kJsBuildLabel[] = "js_build_label"; +const char kJsExceptionCategory[] = "js_exception_category"; +const char kJsExceptionDetails[] = "js_exception_details"; +const char kJsExceptionSignature[] = "js_exception_signature"; + // Convenience wrapper around Value::Dict::FindString(), for easier use in if // statements. If `key` is a string in `dict`, writes it to `out` and returns // true. Leaves `out` alone and returns false otherwise. @@ -102,6 +110,12 @@ result.Set(kSignatureKey, params_.signature); result.Set(kExtraInfoKey, params_.extra_info); result.Set(kCrashProductNameKey, params_.crash_product_name); + result.Set(kComments, params_.comments); + result.Set(kJsEngine, params_.js_engine); + result.Set(kJsBuildLabel, params_.js_build_label); + result.Set(kJsExceptionCategory, params_.js_exception_category); + result.Set(kJsExceptionDetails, params_.js_exception_details); + result.Set(kJsExceptionSignature, params_.js_exception_signature); return base::Value(std::move(result)); } @@ -174,6 +188,25 @@ ++num_params; if (FindString(*dict, kCrashProductNameKey, params_.crash_product_name)) ++num_params; + if (FindString(*dict, kComments, params_.comments)) { + ++num_params; + } + if (FindString(*dict, kJsEngine, params_.js_engine)) { + ++num_params; + } + if (FindString(*dict, kJsBuildLabel, params_.js_build_label)) { + ++num_params; + } + if (FindString(*dict, kJsExceptionCategory, params_.js_exception_category)) { + ++num_params; + } + if (FindString(*dict, kJsExceptionDetails, params_.js_exception_details)) { + ++num_params; + } + if (FindString(*dict, kJsExceptionSignature, + params_.js_exception_signature)) { + ++num_params; + } // Disallow extraneous params if (dict->size() != num_params)
diff --git a/chromecast/crash/linux/dump_info_unittest.cc b/chromecast/crash/linux/dump_info_unittest.cc index 2d86571..12d76a57 100644 --- a/chromecast/crash/linux/dump_info_unittest.cc +++ b/chromecast/crash/linux/dump_info_unittest.cc
@@ -115,7 +115,13 @@ "\"last_app_name\": \"last_app\"," "\"release_version\": \"RELEASE\"," "\"build_number\": \"BUILD_NUMBER\"," - "\"reason\": \"foo\"" + "\"reason\": \"foo\"," + "\"comments\": \"comments\"," + "\"js_engine\": \"js_engine\"," + "\"js_build_label\": \"js_build_label\"," + "\"js_exception_category\": \"js_exception_category\"," + "\"js_exception_details\": \"js_exception_details\"," + "\"js_exception_signature\": \"js_exception_signature\"" "}")); static constexpr base::Time::Exploded kTime = {.year = 2001, .month = 11, @@ -141,6 +147,13 @@ ASSERT_EQ("current_app", info->params().current_app_name); ASSERT_EQ("last_app", info->params().last_app_name); ASSERT_EQ("foo", info->params().reason); + + ASSERT_EQ("comments", info->params().comments); + ASSERT_EQ("js_engine", info->params().js_engine); + ASSERT_EQ("js_build_label", info->params().js_build_label); + ASSERT_EQ("js_exception_category", info->params().js_exception_category); + ASSERT_EQ("js_exception_details", info->params().js_exception_details); + ASSERT_EQ("js_exception_signature", info->params().js_exception_signature); } TEST(DumpInfoTest, SomeOptionalFieldsIsValid) { @@ -152,7 +165,10 @@ "\"uptime\": \"123456789\"," "\"logfile\": \"logfile.log\"," "\"suffix\": \"suffix\"," - "\"prev_app_name\": \"previous_app\"" + "\"prev_app_name\": \"previous_app\"," + "\"comments\": \"comments\"," + "\"js_engine\": \"js_engine\"," + "\"js_build_label\": \"js_build_label\"" "}")); static constexpr base::Time::Exploded kTime = {.year = 2001, .month = 11, @@ -171,6 +187,10 @@ ASSERT_EQ("suffix", info->params().suffix); ASSERT_EQ("previous_app", info->params().previous_app_name); + + ASSERT_EQ("comments", info->params().comments); + ASSERT_EQ("js_engine", info->params().js_engine); + ASSERT_EQ("js_build_label", info->params().js_engine); } TEST(DumpInfoTest, ExtraFieldsIsNotValid) { @@ -187,6 +207,12 @@ "\"last_app_name\": \"last_app\"," "\"release_version\": \"RELEASE\"," "\"build_number\": \"BUILD_NUMBER\"," + "\"comments\": \"comments\"," + "\"js_engine\": \"js_engine\"," + "\"js_build_label\": \"js_build_label\"," + "\"js_exception_category\": \"js_exception_category\"," + "\"js_exception_details\": \"js_exception_details\"," + "\"js_exception_signature\": \"js_exception_signature\"," "\"hello\": \"extra_field\"" "}")); ASSERT_FALSE(info->valid());
diff --git a/chromecast/crash/linux/minidump_params.cc b/chromecast/crash/linux/minidump_params.cc index 2730006..eb25aa24 100644 --- a/chromecast/crash/linux/minidump_params.cc +++ b/chromecast/crash/linux/minidump_params.cc
@@ -18,7 +18,13 @@ const std::string& p_extra_info, const std::string& p_exec_name, const std::string& p_signature, - const std::string& p_crash_product_name) + const std::string& p_crash_product_name, + const std::string& p_comments, + const std::string& p_js_engine, + const std::string& p_js_build_label, + const std::string& p_js_exception_category, + const std::string& p_js_exception_details, + const std::string& p_js_exception_signature) : process_uptime(p_process_uptime), suffix(p_suffix), previous_app_name(p_previous_app_name), @@ -31,7 +37,13 @@ extra_info(p_extra_info), exec_name(p_exec_name), signature(p_signature), - crash_product_name(p_crash_product_name) {} + crash_product_name(p_crash_product_name), + comments(p_comments), + js_engine(p_js_engine), + js_build_label(p_js_build_label), + js_exception_category(p_js_exception_category), + js_exception_details(p_js_exception_details), + js_exception_signature(p_js_exception_signature) {} MinidumpParams::MinidumpParams() : process_uptime(0) {}
diff --git a/chromecast/crash/linux/minidump_params.h b/chromecast/crash/linux/minidump_params.h index 281fb7d..07d73d0 100644 --- a/chromecast/crash/linux/minidump_params.h +++ b/chromecast/crash/linux/minidump_params.h
@@ -25,7 +25,13 @@ const std::string& p_extra_info = "", const std::string& p_exec_name = "", const std::string& p_signature = "", - const std::string& p_crash_product_name = ""); + const std::string& p_crash_product_name = "", + const std::string& p_comments = "", + const std::string& p_js_engine = "", + const std::string& p_js_build_label = "", + const std::string& p_js_exception_category = "", + const std::string& p_js_exception_details = "", + const std::string& p_js_exception_signature = ""); MinidumpParams(const MinidumpParams& params); ~MinidumpParams(); @@ -47,6 +53,14 @@ std::string signature; // Crash Product name, used to identify/group crash reports in go/crash. std::string crash_product_name; + + // CastLite specific crash report data + std::string comments; + std::string js_engine; + std::string js_build_label; + std::string js_exception_category; + std::string js_exception_details; + std::string js_exception_signature; }; } // namespace chromecast
diff --git a/chromecast/crash/linux/minidump_uploader.cc b/chromecast/crash/linux/minidump_uploader.cc index a78cda2..d1b660f 100644 --- a/chromecast/crash/linux/minidump_uploader.cc +++ b/chromecast/crash/linux/minidump_uploader.cc
@@ -303,6 +303,29 @@ } } + // Set CastLite specific crash report data. + if (!dump.params().comments.empty()) { + g.SetParameter("comments", dump.params().comments); + } + if (!dump.params().js_engine.empty()) { + g.SetParameter("js_engine", dump.params().js_engine); + } + if (!dump.params().js_build_label.empty()) { + g.SetParameter("js_build_label", dump.params().js_build_label); + } + if (!dump.params().js_exception_category.empty()) { + g.SetParameter("js_exception_category", + dump.params().js_exception_category); + } + if (!dump.params().js_exception_details.empty()) { + g.SetParameter("js_exception_details", + dump.params().js_exception_details); + } + if (!dump.params().js_exception_signature.empty()) { + // Upload as "signature" to populate the "Stable Signature" field + g.SetParameter("signature", dump.params().js_exception_signature); + } + std::string response; if (!g.Upload(&response)) { // We have failed to upload this file.
diff --git a/chromecast/external_mojo/external_service_support/crash_reporter_system.cc b/chromecast/external_mojo/external_service_support/crash_reporter_system.cc index c7ee710d..9588b8e 100644 --- a/chromecast/external_mojo/external_service_support/crash_reporter_system.cc +++ b/chromecast/external_mojo/external_service_support/crash_reporter_system.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/command_line.h" +#include "chromecast/base/chromecast_switches.h" #include "chromecast/external_mojo/external_service_support/crash_reporter_client.h" #include "third_party/crashpad/crashpad/client/crashpad_info.h" @@ -10,8 +12,17 @@ // static void CrashReporterClient::Init() { - crashpad::CrashpadInfo::GetCrashpadInfo() - ->set_system_crash_reporter_forwarding(crashpad::TriState::kEnabled); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + crashpad::CrashpadInfo* crashpad_info = + crashpad::CrashpadInfo::GetCrashpadInfo(); + if (command_line->HasSwitch(switches::kDisableCrashpadForwarding)) { + LOG(INFO) << "Crashpad forwarding disabled"; + crashpad_info->set_system_crash_reporter_forwarding( + crashpad::TriState::kDisabled); + } else { + crashpad_info->set_system_crash_reporter_forwarding( + crashpad::TriState::kEnabled); + } } } // namespace external_service_support
diff --git a/chromeos/ash/components/audio/BUILD.gn b/chromeos/ash/components/audio/BUILD.gn index 9b49380e..a0f2f98e 100644 --- a/chromeos/ash/components/audio/BUILD.gn +++ b/chromeos/ash/components/audio/BUILD.gn
@@ -47,6 +47,7 @@ "cros_audio_config.h", "cros_audio_config_impl.cc", "cros_audio_config_impl.h", + "device_activate_type.h", "sounds.h", ] }
diff --git a/chromeos/ash/components/audio/audio_selection_notification_handler.cc b/chromeos/ash/components/audio/audio_selection_notification_handler.cc index efa3de6..d8c09e9d 100644 --- a/chromeos/ash/components/audio/audio_selection_notification_handler.cc +++ b/chromeos/ash/components/audio/audio_selection_notification_handler.cc
@@ -93,7 +93,8 @@ const AudioDeviceList& hotplug_input_devices, const AudioDeviceList& hotplug_output_devices, const std::optional<std::string>& active_input_device_name, - const std::optional<std::string>& active_output_device_name) { + const std::optional<std::string>& active_output_device_name, + SwitchToDeviceCallback switch_to_device_callback) { // At least input or output has hotplug device. CHECK(!hotplug_input_devices.empty() || !hotplug_output_devices.empty()); @@ -177,9 +178,9 @@ /*delegate=*/ base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( base::BindRepeating( - &AudioSelectionNotificationHandler::HandleNotificationClicked, - weak_ptr_factory_.GetWeakPtr(), - /*is_settings_button=*/false, devices_to_activate))}; + &AudioSelectionNotificationHandler::HandleSwitchButtonClicked, + weak_ptr_factory_.GetWeakPtr(), devices_to_activate, + switch_to_device_callback))}; auto* message_center = message_center::MessageCenter::Get(); message_center->RemoveNotification(notification.id(), /*by_user=*/false); @@ -189,12 +190,28 @@ // TODO(zhangwenyu): Add metrics to record notification is displayed. } -void AudioSelectionNotificationHandler::HandleNotificationClicked( - bool is_settings_button, +void AudioSelectionNotificationHandler::HandleSwitchButtonClicked( const AudioDeviceList& devices_to_activate, + SwitchToDeviceCallback switch_to_device_callback, std::optional<int> button_index) { + if (!button_index.has_value()) { + // Do not do anything when notification body is clicked. If the button is + // clicked, the button_index will have a value. + return; + } + // TODO(zhangwenyu): Add metrics to record notification button clicked. - // TODO(zhangwenyu): Activate the devices when switch button is clicked. + + // Activate audio devices. + for (const AudioDevice& device : devices_to_activate) { + switch_to_device_callback.Run(device, /*notify=*/true, + DeviceActivateType::kActivateByUser); + } + + // Remove notification. + auto* message_center = message_center::MessageCenter::Get(); + message_center->RemoveNotification(kAudioSelectionNotificationId, + /*by_user=*/true); } AudioSelectionNotificationHandler::NotificationTemplate
diff --git a/chromeos/ash/components/audio/audio_selection_notification_handler.h b/chromeos/ash/components/audio/audio_selection_notification_handler.h index 01b97e5d..8f543bb6 100644 --- a/chromeos/ash/components/audio/audio_selection_notification_handler.h +++ b/chromeos/ash/components/audio/audio_selection_notification_handler.h
@@ -8,13 +8,22 @@ #include <optional> #include "base/component_export.h" +#include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" #include "chromeos/ash/components/audio/audio_device.h" #include "chromeos/ash/components/audio/audio_device_id.h" +#include "chromeos/ash/components/audio/device_activate_type.h" #include "ui/message_center/message_center.h" namespace ash { +// A callback of CrasAudioHandler::SwitchToDevice function, used to handle the +// switch button on audio selection notification being clicked. +using SwitchToDeviceCallback = + base::RepeatingCallback<void(const AudioDevice& device, + bool notify, + DeviceActivateType activate_by)>; + // AudioSelectionNotificationHandler handles the creation and display of the // audio selection notification. class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_AUDIO) @@ -76,16 +85,18 @@ const AudioDeviceList& hotplug_input_devices, const AudioDeviceList& hotplug_output_devices, const std::optional<std::string>& active_input_device_name, - const std::optional<std::string>& active_output_device_name); + const std::optional<std::string>& active_output_device_name, + SwitchToDeviceCallback switch_to_device_callback); private: // Grant friend access for comprehensive testing of private/protected members. friend class AudioSelectionNotificationHandlerTest; - // Handles when the notification button is clicked. - void HandleNotificationClicked(bool is_settings_button, - const AudioDeviceList& devices_to_activate, - std::optional<int> button_index); + // Handles when the switch button is clicked. + void HandleSwitchButtonClicked( + const AudioDeviceList& devices_to_activate, + SwitchToDeviceCallback switch_to_device_callback, + std::optional<int> button_index); // Checks if one audio input device and one audio output device belong to the // same physical audio device.
diff --git a/chromeos/ash/components/audio/audio_selection_notification_handler_unittest.cc b/chromeos/ash/components/audio/audio_selection_notification_handler_unittest.cc index 6e47e122..9b01f98e 100644 --- a/chromeos/ash/components/audio/audio_selection_notification_handler_unittest.cc +++ b/chromeos/ash/components/audio/audio_selection_notification_handler_unittest.cc
@@ -20,6 +20,12 @@ void TearDown() override { message_center::MessageCenter::Shutdown(); } + static void SwitchToDevice(const AudioDevice& device, + bool notify, + DeviceActivateType activate_by) { + CrasAudioHandler::Get()->SwitchToDevice(device, notify, activate_by); + } + AudioSelectionNotificationHandler& audio_selection_notification_handler() { return audio_selection_notification_handler_; } @@ -30,6 +36,26 @@ input_device, output_device); } + void FakeSwitchToDevice(const AudioDevice& device, + bool notify, + DeviceActivateType activate_by) { + if (device.is_input) { + active_input_id_ = device.id; + } else { + active_output_id_ = device.id; + } + } + + void HandleSwitchButtonClicked(const AudioDeviceList& devices_to_activate, + std::optional<int> button_index) { + audio_selection_notification_handler_.HandleSwitchButtonClicked( + devices_to_activate, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::FakeSwitchToDevice, + weak_ptr_factory_.GetWeakPtr()), + button_index); + } + // Gets the count of audio selection notification. size_t GetNotificationCount() { auto* message_center = message_center::MessageCenter::Get(); @@ -58,8 +84,16 @@ : std::nullopt; } + uint64_t active_input_id() { return active_input_id_; } + + uint64_t active_output_id() { return active_output_id_; } + private: AudioSelectionNotificationHandler audio_selection_notification_handler_; + uint64_t active_input_id_; + uint64_t active_output_id_; + base::WeakPtrFactory<AudioSelectionNotificationHandlerTest> weak_ptr_factory_{ + this}; }; TEST_F(AudioSelectionNotificationHandlerTest, ShowAudioSelectionNotification) { @@ -71,8 +105,9 @@ AudioDevice(NewOutputNode("INTERNAL_SPEAKER"))}; audio_selection_notification_handler().ShowAudioSelectionNotification( - hotplug_input_devices, hotplug_output_devices, std::nullopt, - std::nullopt); + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); // Expect notification is shown. EXPECT_EQ(1u, GetNotificationCount()); @@ -82,8 +117,9 @@ hotplug_input_devices = {AudioDevice(NewInputNode("MIC"))}; hotplug_output_devices = {AudioDevice(NewOutputNode("HEADPHONE"))}; audio_selection_notification_handler().ShowAudioSelectionNotification( - hotplug_input_devices, hotplug_output_devices, std::nullopt, - std::nullopt); + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); } @@ -163,8 +199,9 @@ /*is_input=*/true, "USB", input_device_name))}; AudioDeviceList hotplug_output_devices = {}; audio_selection_notification_handler().ShowAudioSelectionNotification( - hotplug_input_devices, hotplug_output_devices, std::nullopt, - std::nullopt); + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); std::optional<std::u16string> title = GetNotificationTitle(); EXPECT_TRUE(title.has_value()); @@ -190,8 +227,9 @@ AudioDeviceList hotplug_output_devices = {AudioDevice(NewNodeWithName( /*is_input=*/false, "HDMI", output_device_name))}; audio_selection_notification_handler().ShowAudioSelectionNotification( - hotplug_input_devices, hotplug_output_devices, std::nullopt, - std::nullopt); + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); std::optional<std::u16string> title = GetNotificationTitle(); EXPECT_TRUE(title.has_value()); @@ -223,8 +261,9 @@ AudioDeviceList hotplug_output_devices = {AudioDevice( NewNodeWithName(/*is_input=*/false, "USB", output_device_name))}; audio_selection_notification_handler().ShowAudioSelectionNotification( - hotplug_input_devices, hotplug_output_devices, std::nullopt, - std::nullopt); + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); std::optional<std::u16string> title = GetNotificationTitle(); EXPECT_TRUE(title.has_value()); @@ -257,7 +296,9 @@ const std::string current_active_output = "internal_speaker"; audio_selection_notification_handler().ShowAudioSelectionNotification( hotplug_input_devices, hotplug_output_devices, current_active_input, - current_active_output); + current_active_output, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); std::optional<std::u16string> title = GetNotificationTitle(); EXPECT_TRUE(title.has_value()); @@ -291,7 +332,9 @@ const std::string current_active_output = "internal_speaker"; audio_selection_notification_handler().ShowAudioSelectionNotification( hotplug_input_devices, hotplug_output_devices, current_active_input, - current_active_output); + current_active_output, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); EXPECT_EQ(1u, GetNotificationCount()); std::optional<std::u16string> title = GetNotificationTitle(); EXPECT_TRUE(title.has_value()); @@ -307,4 +350,36 @@ message.value()); } +// Tests clicking switch button on notification should activate the device. +TEST_F(AudioSelectionNotificationHandlerTest, HandleSwitchButtonClicked) { + EXPECT_EQ(0u, GetNotificationCount()); + + // Plug HTMI display with audio output. + AudioDeviceList hotplug_input_devices = {}; + const std::string output_device_name = "Sceptre Z27"; + const AudioDevice output_hdmi = AudioDevice(NewNodeWithName( + /*is_input=*/false, "HDMI", output_device_name)); + AudioDeviceList hotplug_output_devices = {output_hdmi}; + audio_selection_notification_handler().ShowAudioSelectionNotification( + hotplug_input_devices, hotplug_output_devices, std::nullopt, std::nullopt, + base::BindRepeating( + &AudioSelectionNotificationHandlerTest::SwitchToDevice)); + + // Expect notification displays. + EXPECT_EQ(1u, GetNotificationCount()); + + // Clicking notification body does not have any effects. + HandleSwitchButtonClicked({output_hdmi}, std::nullopt); + EXPECT_NE(output_hdmi.id, active_output_id()); + EXPECT_EQ(1u, GetNotificationCount()); + + // Clicking switch button, expect device being activated and notification is + // removed. + HandleSwitchButtonClicked({output_hdmi}, + /*button_index=*/1); + + EXPECT_EQ(output_hdmi.id, active_output_id()); + EXPECT_EQ(0u, GetNotificationCount()); +} + } // namespace ash
diff --git a/chromeos/ash/components/audio/cras_audio_handler.cc b/chromeos/ash/components/audio/cras_audio_handler.cc index a58095e..7095aa7 100644 --- a/chromeos/ash/components/audio/cras_audio_handler.cc +++ b/chromeos/ash/components/audio/cras_audio_handler.cc
@@ -303,7 +303,8 @@ // Switch to front mic properly. DeviceActivateType activated_by = - HasExternalDevice(true) ? ACTIVATE_BY_USER : ACTIVATE_BY_PRIORITY; + HasExternalDevice(true) ? DeviceActivateType::kActivateByUser + : DeviceActivateType::kActivateByPriority; SwitchToDevice(*GetDeviceByType(AudioDeviceType::kFrontMic), true, activated_by); } @@ -780,7 +781,7 @@ // If there is no primary active device, set |node_id| to primary active node. if ((device->is_input && !active_input_node_id_) || (!device->is_input && !active_output_node_id_)) { - SwitchToDevice(*device, notify, ACTIVATE_BY_USER); + SwitchToDevice(*device, notify, DeviceActivateType::kActivateByUser); return; } @@ -852,7 +853,8 @@ is_input ? active_input_node_id_ : active_output_node_id_; if (!new_active_ids.count(primary_active) && !devices.empty()) { active_devices_changed = true; - SwitchToDevice(devices[0], false /* notify */, ACTIVATE_BY_USER); + SwitchToDevice(devices[0], false /* notify */, + DeviceActivateType::kActivateByUser); } AudioDeviceList existing_devices; @@ -1107,7 +1109,7 @@ void CrasAudioHandler::SetActiveDevice(const AudioDevice& active_device, bool notify, DeviceActivateType activate_by) { - if (activate_by == ACTIVATE_BY_USER) { + if (activate_by == DeviceActivateType::kActivateByUser) { audio_device_metrics_handler_.RecordUserSwitchAudioDevice( active_device.is_input); } else { @@ -1122,10 +1124,10 @@ // Including to unset it when selected by priority or by camera. if (active_device.is_input) { audio_device_metrics_handler_.set_input_device_selected_by_user( - activate_by == ACTIVATE_BY_USER); + activate_by == DeviceActivateType::kActivateByUser); } else { audio_device_metrics_handler_.set_output_device_selected_by_user( - activate_by == ACTIVATE_BY_USER); + activate_by == DeviceActivateType::kActivateByUser); } if (active_device.is_input) { @@ -1166,10 +1168,10 @@ audio_pref_handler_->SetDeviceActive(device, false, false); } else { switch (activate_by) { - case ACTIVATE_BY_USER: + case DeviceActivateType::kActivateByUser: audio_pref_handler_->SetDeviceActive(device, true, true); break; - case ACTIVATE_BY_PRIORITY: + case DeviceActivateType::kActivateByPriority: audio_pref_handler_->SetDeviceActive(device, true, false); break; default: @@ -1817,7 +1819,7 @@ DeviceActivateType activate_by) { if (!ChangeActiveDevice(device)) { // Record the decision of system not switching active device. - if (activate_by != ACTIVATE_BY_USER) { + if (activate_by != DeviceActivateType::kActivateByUser) { audio_device_metrics_handler_.MaybeRecordSystemSwitchDecisionAndContext( device.is_input, device.is_input ? has_alternative_input_ : has_alternative_output_, @@ -2126,7 +2128,8 @@ } if (ShouldSwitchToHotPlugDevice(hotplug_device)) { - SwitchToDevice(hotplug_device, true, ACTIVATE_BY_PRIORITY); + SwitchToDevice(hotplug_device, true, + DeviceActivateType::kActivateByPriority); return; } else { // Record the decision of system not switching active device. @@ -2161,7 +2164,7 @@ return; } - SwitchToDevice(top_device, true, ACTIVATE_BY_PRIORITY); + SwitchToDevice(top_device, true, DeviceActivateType::kActivateByPriority); } void CrasAudioHandler::SwitchToPreviousActiveDeviceIfAvailable( @@ -2172,7 +2175,7 @@ DCHECK(previous_active_device.is_for_simple_usage()); // Switch to previous active device stored in user prefs. SwitchToDevice(previous_active_device, true, - ACTIVATE_BY_RESTORE_PREVIOUS_STATE); + DeviceActivateType::kActivateByRestorePreviousState); } else { // No previous active device, switch to the top priority device. SwitchToTopPriorityDevice(devices); @@ -2278,7 +2281,9 @@ : std::nullopt, active_output_device ? std::make_optional(active_output_device->display_name) - : std::nullopt); + : std::nullopt, + base::BindRepeating(&CrasAudioHandler::SwitchToDevice, + weak_ptr_factory_.GetWeakPtr())); // Reset show notification flag. should_show_notification_ = false; @@ -2500,7 +2505,7 @@ return; } - SwitchToDevice(*mic, true, ACTIVATE_BY_CAMERA); + SwitchToDevice(*mic, true, DeviceActivateType::kActivateByCamera); } void CrasAudioHandler::ActivateInternalMicForActiveCamera() { @@ -2525,7 +2530,7 @@ ActivateInternalMicForActiveCamera(); } else { SwitchToDevice(*GetDeviceByType(AudioDeviceType::kFrontMic), true, - ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); } } @@ -2848,7 +2853,8 @@ // kAudioSelectionImprovement flag is on. CHECK(features::IsAudioSelectionImprovementEnabled()); if (hotplug_device.has_privilege()) { - SwitchToDevice(hotplug_device, /*notify=*/true, ACTIVATE_BY_PRIORITY); + SwitchToDevice(hotplug_device, /*notify=*/true, + DeviceActivateType::kActivateByPriority); // Record audio selection exception rule #1. audio_device_metrics_handler_.RecordExceptionRulesMet( @@ -2871,7 +2877,8 @@ // activated. if (preferred_device.has_value() && preferred_device->stable_device_id == hotplug_device.stable_device_id) { - SwitchToDevice(hotplug_device, /*notify=*/true, ACTIVATE_BY_PRIORITY); + SwitchToDevice(hotplug_device, /*notify=*/true, + DeviceActivateType::kActivateByPriority); return; }
diff --git a/chromeos/ash/components/audio/cras_audio_handler.h b/chromeos/ash/components/audio/cras_audio_handler.h index 1501166..7fbfd52 100644 --- a/chromeos/ash/components/audio/cras_audio_handler.h +++ b/chromeos/ash/components/audio/cras_audio_handler.h
@@ -239,13 +239,6 @@ virtual ~AudioObserver(); }; - enum DeviceActivateType { - ACTIVATE_BY_PRIORITY = 0, - ACTIVATE_BY_USER, - ACTIVATE_BY_RESTORE_PREVIOUS_STATE, - ACTIVATE_BY_CAMERA - }; - enum class ClientType { CHROME = 0, ARC,
diff --git a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc index ef6532ed..92122a0d 100644 --- a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc +++ b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc
@@ -24,6 +24,7 @@ #include "base/values.h" #include "chromeos/ash/components/audio/audio_devices_pref_handler.h" #include "chromeos/ash/components/audio/audio_devices_pref_handler_stub.h" +#include "chromeos/ash/components/audio/audio_selection_notification_handler.h" #include "chromeos/ash/components/dbus/audio/audio_node.h" #include "chromeos/ash/components/dbus/audio/fake_cras_audio_client.h" #include "media/base/video_facing.h" @@ -846,7 +847,7 @@ // Switch the active output to internal speaker. AudioDevice internal_speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker, and the // ActiveOutputNodeChanged event is fired. @@ -871,7 +872,7 @@ // Switch the active input to internal mic. AudioDevice internal_mic(GenerateAudioNode(kInternalMic)); cras_audio_handler_->SwitchToDevice(internal_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker, and the active // ActiveInputNodeChanged event is fired. @@ -1576,7 +1577,7 @@ // Select the speaker to be the active output device. AudioDevice internal_speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker, and the // ActiveOutputNodeChanged event is fired. @@ -1932,7 +1933,7 @@ // Switch the active output to internal speaker. AudioDevice internal_speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker, and the // ActiveOutputNodeChanged event is fired. @@ -1995,7 +1996,7 @@ // Switch the active output to internal speaker. AudioDevice internal_speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker, and the // ActiveOutputNodeChanged event is fired. @@ -3253,7 +3254,7 @@ // higher preference priority than USB headphone. AudioDevice speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_NE(kUSBHeadphone1->id, cras_audio_handler_->GetPrimaryActiveOutputNode()); @@ -3343,7 +3344,7 @@ // higher preference priority than USB headphone. AudioDevice speaker(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(speaker, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_NE(kUSBHeadphone1->id, cras_audio_handler_->GetPrimaryActiveOutputNode()); @@ -3381,7 +3382,7 @@ // device has higher preference priority. AudioDevice usb_headset2_device(GenerateAudioNode(kUSBHeadphone2)); cras_audio_handler_->SwitchToDevice(usb_headset2_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(kUSBHeadphone2->id, cras_audio_handler_->GetPrimaryActiveOutputNode()); @@ -3592,7 +3593,7 @@ // Switch the active output to internal speaker. cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalSpeaker)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify internal speaker has been made active. AudioDeviceList audio_devices; @@ -3627,7 +3628,7 @@ // Switch the active output to internal speaker. cras_audio_handler_->SwitchToDevice( AudioDevice(GenerateAudioNode(kInternalSpeaker)), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify internal speaker has been made active. AudioDeviceList audio_devices; @@ -4509,11 +4510,11 @@ // Manually select internal speaker as active output. AudioDevice internal_output(internal_speaker); cras_audio_handler_->SwitchToDevice(internal_output, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Manually select internal mic as active input. AudioDevice internal_input(internal_mic); cras_audio_handler_->SwitchToDevice(internal_input, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker. EXPECT_EQ(internal_speaker.id, @@ -4626,11 +4627,11 @@ // Manually select internal speaker as active output. AudioDevice internal_output(internal_speaker); cras_audio_handler_->SwitchToDevice(internal_output, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Manually select internal mic as active input. AudioDevice internal_input(internal_mic); cras_audio_handler_->SwitchToDevice(internal_input, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker. EXPECT_EQ(internal_speaker.id, @@ -4747,11 +4748,11 @@ // Manually select internal speaker as active output. AudioDevice internal_output(internal_speaker); cras_audio_handler_->SwitchToDevice(internal_output, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Manually select internal mic as active input. AudioDevice internal_input(internal_mic); cras_audio_handler_->SwitchToDevice(internal_input, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker. EXPECT_EQ(internal_speaker.id, @@ -4936,7 +4937,7 @@ // Manually set the active output to internal speaker. AudioDevice internal_output(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_output, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker. EXPECT_EQ(internal_speaker.id, @@ -4985,7 +4986,7 @@ // Manually set the active output to internal speaker. AudioDevice internal_output(GenerateAudioNode(kInternalSpeaker)); cras_audio_handler_->SwitchToDevice(internal_output, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); // Verify the active output is switched to internal speaker. EXPECT_EQ(internal_speaker.id, @@ -5060,7 +5061,7 @@ // Manually set the active output to internal speaker. AudioNode internal_speaker = GenerateAudioNode(kInternalSpeaker); cras_audio_handler_->SwitchToDevice(AudioDevice(internal_speaker), true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(internal_speaker.id, cras_audio_handler_->GetPrimaryActiveOutputNode()); @@ -6291,7 +6292,7 @@ // Now USB is the preferred device among USB, internal and HDMI device. AudioDevice usb_output_device(usb_output); cras_audio_handler_->SwitchToDevice(usb_output_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(1, test_observer_->active_output_node_changed_count()); EXPECT_TRUE( @@ -6312,7 +6313,7 @@ // Activate internal speaker. Expect active device is the internal speaker. AudioDevice internal_speaker_device(internal_speaker); cras_audio_handler_->SwitchToDevice(internal_speaker_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_EQ(3, test_observer_->active_output_node_changed_count()); EXPECT_TRUE( @@ -6554,7 +6555,7 @@ // Activate HDMI output device, expect HDMI output device becomes active. AudioDevice hdmi_output_device(hdmi_output); cras_audio_handler_->SwitchToDevice(hdmi_output_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_TRUE( cras_audio_handler_->GetPrimaryActiveOutputDevice(&active_output)); @@ -6645,7 +6646,7 @@ // Activate USB input1 device, expect USB input1 device becomes active. AudioDevice usb_input1_device(usb_input1); cras_audio_handler_->SwitchToDevice(usb_input1_device, true, - CrasAudioHandler::ACTIVATE_BY_USER); + DeviceActivateType::kActivateByUser); EXPECT_TRUE(cras_audio_handler_->GetPrimaryActiveInputDevice(&active_input)); EXPECT_EQ(kUSBMic1->id, active_input.id);
diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.cc b/chromeos/ash/components/audio/cros_audio_config_impl.cc index 8397271..31f0f75 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl.cc
@@ -323,9 +323,8 @@ audio_handler->IsFrontOrRearMic(*next_active_device)) { audio_handler->SwitchToFrontOrRearMic(); } else { - audio_handler->SwitchToDevice( - *next_active_device, /*notify=*/true, - CrasAudioHandler::DeviceActivateType::ACTIVATE_BY_USER); + audio_handler->SwitchToDevice(*next_active_device, /*notify=*/true, + DeviceActivateType::kActivateByUser); } // Record if it was an output or input device that changed.
diff --git a/chromeos/ash/components/audio/device_activate_type.h b/chromeos/ash/components/audio/device_activate_type.h new file mode 100644 index 0000000..ca673b20 --- /dev/null +++ b/chromeos/ash/components/audio/device_activate_type.h
@@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_AUDIO_DEVICE_ACTIVATE_TYPE_H_ +#define CHROMEOS_ASH_COMPONENTS_AUDIO_DEVICE_ACTIVATE_TYPE_H_ + +namespace ash { + +// Indicates the source that activates an audio device. +enum class DeviceActivateType { + kActivateByPriority = 0, + kActivateByUser = 1, + kActivateByRestorePreviousState = 2, + kActivateByCamera = 3, + kMaxValue = kActivateByCamera, +}; + +} // namespace ash + +#endif // CHROMEOS_ASH_COMPONENTS_AUDIO_DEVICE_ACTIVATE_TYPE_H_
diff --git a/chromeos/ash/components/data_migration/data_migration_unittest.cc b/chromeos/ash/components/data_migration/data_migration_unittest.cc index 9aa7ec36..2fbddef 100644 --- a/chromeos/ash/components/data_migration/data_migration_unittest.cc +++ b/chromeos/ash/components/data_migration/data_migration_unittest.cc
@@ -22,12 +22,12 @@ #include "base/test/run_until.h" #include "base/test/scoped_path_override.h" #include "base/test/task_environment.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/testing/connection_barrier.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_connections.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_process_manager.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/data_migration/device_unittest.cc b/chromeos/ash/components/data_migration/device_unittest.cc index 5c3328ed..57fb9262 100644 --- a/chromeos/ash/components/data_migration/device_unittest.cc +++ b/chromeos/ash/components/data_migration/device_unittest.cc
@@ -27,12 +27,12 @@ #include "base/test/scoped_run_loop_timeout.h" #include "base/test/task_environment.h" #include "base/timer/timer.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/testing/connection_barrier.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_connections.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_process_manager.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/data_migration/file_receiver_unittest.cc b/chromeos/ash/components/data_migration/file_receiver_unittest.cc index 291ca95..421ad251 100644 --- a/chromeos/ash/components/data_migration/file_receiver_unittest.cc +++ b/chromeos/ash/components/data_migration/file_receiver_unittest.cc
@@ -13,12 +13,12 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/testing/connection_barrier.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_connections.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_process_manager.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/data_migration/file_transfer_unittest.cc b/chromeos/ash/components/data_migration/file_transfer_unittest.cc index 085087d..dd47594 100644 --- a/chromeos/ash/components/data_migration/file_transfer_unittest.cc +++ b/chromeos/ash/components/data_migration/file_transfer_unittest.cc
@@ -19,13 +19,13 @@ #include "base/test/scoped_path_override.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/pending_file_transfer_queue.h" #include "chromeos/ash/components/data_migration/testing/connection_barrier.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_connections.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_process_manager.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/data_migration/rts_receiver_unittest.cc b/chromeos/ash/components/data_migration/rts_receiver_unittest.cc index b1e7848..09341043 100644 --- a/chromeos/ash/components/data_migration/rts_receiver_unittest.cc +++ b/chromeos/ash/components/data_migration/rts_receiver_unittest.cc
@@ -10,13 +10,13 @@ #include "base/functional/callback_helpers.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" #include "chromeos/ash/components/data_migration/constants.h" #include "chromeos/ash/components/data_migration/pending_file_transfer_queue.h" #include "chromeos/ash/components/data_migration/testing/connection_barrier.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_connections.h" #include "chromeos/ash/components/data_migration/testing/fake_nearby_process_manager.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromeos/ash/components/dbus/concierge/concierge_client.cc b/chromeos/ash/components/dbus/concierge/concierge_client.cc index a51c84e..e20de026 100644 --- a/chromeos/ash/components/dbus/concierge/concierge_client.cc +++ b/chromeos/ash/components/dbus/concierge/concierge_client.cc
@@ -226,24 +226,8 @@ const concierge::AttachUsbDeviceRequest& request, chromeos::DBusMethodCallback<concierge::AttachUsbDeviceResponse> callback) override { - dbus::MethodCall method_call(concierge::kVmConciergeInterface, - concierge::kAttachUsbDeviceMethod); - dbus::MessageWriter writer(&method_call); - - if (!writer.AppendProtoAsArrayOfBytes(request)) { - LOG(ERROR) << "Failed to encode AttachUsbDeviceRequest protobuf"; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::nullopt)); - return; - } - - writer.AppendFileDescriptor(fd.get()); - - concierge_proxy_->CallMethod( - &method_call, kConciergeDBusTimeoutMs, - base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse< - concierge::AttachUsbDeviceResponse>, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + CallMethodWithFd(concierge::kAttachUsbDeviceMethod, request, std::move(fd), + std::move(callback)); } void DetachUsbDevice( @@ -364,8 +348,7 @@ if (!writer.AppendProtoAsArrayOfBytes(request)) { LOG(ERROR) << "Failed to encode protobuf for " << method_name; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::nullopt)); + std::move(callback).Run(std::nullopt); return; } @@ -395,8 +378,7 @@ if (!writer.AppendProtoAsArrayOfBytes(request)) { LOG(ERROR) << "Failed to encode protobuf for " << method_name; - base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), std::nullopt)); + std::move(callback).Run(std::nullopt); return; }
diff --git a/chromeos/ash/components/nearby/common/BUILD.gn b/chromeos/ash/components/nearby/common/BUILD.gn index 761516d..e9f0ecc6 100644 --- a/chromeos/ash/components/nearby/common/BUILD.gn +++ b/chromeos/ash/components/nearby/common/BUILD.gn
@@ -11,6 +11,7 @@ defines = [ "IS_CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_IMPL" ] deps = [ "//chromeos/ash/components/nearby/common/client", + "//chromeos/ash/components/nearby/common/connections_manager", "//chromeos/ash/components/nearby/common/scheduling", ] } @@ -21,6 +22,7 @@ deps = [ ":common", "//chromeos/ash/components/nearby/common/client:unit_tests", + "//chromeos/ash/components/nearby/common/connections_manager:unit_tests", "//chromeos/ash/components/nearby/common/scheduling:unit_tests", ] }
diff --git a/chromeos/ash/components/nearby/common/connections_manager/BUILD.gn b/chromeos/ash/components/nearby/common/connections_manager/BUILD.gn index b9bd95e..97c282f 100644 --- a/chromeos/ash/components/nearby/common/connections_manager/BUILD.gn +++ b/chromeos/ash/components/nearby/common/connections_manager/BUILD.gn
@@ -14,19 +14,29 @@ "nearby_connection_impl.h", "nearby_connections_manager.cc", "nearby_connections_manager.h", + "nearby_connections_manager_impl.cc", + "nearby_connections_manager_impl.h", "nearby_file_handler.cc", "nearby_file_handler.h", ] deps = [ - "//base", "//chrome/browser/nearby_sharing/common", - "//chromeos/ash/components/nearby/presence:presence", - "//chromeos/ash/services/nearby/public/mojom", + "//chromeos/ash/components/nearby/presence/conversions:conversions", + "//components/cross_device/logging:logging", + "//components/cross_device/nearby:nearby", "//third_party/abseil-cpp:absl", ] - public_deps = [ "//third_party/nearby:presence_types" ] + public_deps = [ + "//base", + "//chromeos/ash/components/nearby/presence:presence", + "//chromeos/ash/services/nearby/public/cpp:cpp", + "//chromeos/ash/services/nearby/public/mojom", + "//components/cross_device/nearby:platform", + "//net", + "//third_party/nearby:presence_types", + ] } source_set("test_support") { @@ -42,7 +52,41 @@ deps = [ ":connections_manager", "//base", + "//base/test:test_support", + "//chrome/test:test_support", + "//chromeos/ash/services/nearby/public/cpp:test_support", "//chromeos/ash/services/nearby/public/mojom", + "//content/test:test_support", + "//net:test_support", + "//net/traffic_annotation:test_support", + "//services/network:test_support", + "//testing/gmock", + "//testing/gtest", + ] + + public_deps = [ "//third_party/nearby:presence_types" ] +} + +source_set("unit_tests") { + testonly = true + + sources = [ "nearby_connections_manager_impl_unittest.cc" ] + + deps = [ + ":connections_manager", + ":test_support", + "//base", + "//base/test:test_support", + "//chrome/test:test_support", + "//chromeos/ash/services/nearby/public/cpp:test_support", + "//chromeos/ash/services/nearby/public/mojom", + "//components/cross_device/nearby:nearby", + "//content/test:test_support", + "//net:test_support", + "//net/traffic_annotation:test_support", + "//services/network:test_support", + "//testing/gmock", + "//testing/gtest", ] public_deps = [ "//third_party/nearby:presence_types" ]
diff --git a/chromeos/ash/components/nearby/common/connections_manager/DEPS b/chromeos/ash/components/nearby/common/connections_manager/DEPS index 8743afe..4f574c7 100644 --- a/chromeos/ash/components/nearby/common/connections_manager/DEPS +++ b/chromeos/ash/components/nearby/common/connections_manager/DEPS
@@ -1,3 +1,11 @@ include_rules = [ '+components/cross_device/nearby/nearby_features.h', -] \ No newline at end of file + "+components/cross_device/logging", +] + +specific_include_rules = { + ".*_unittest.cc": [ + "+chrome/test/base/testing_browser_process.h", + "+content/public/test", + ], +}
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc similarity index 99% rename from chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc rename to chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc index a064375..cf1770e 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc +++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include "base/containers/contains.h" #include "base/files/file_util.h" @@ -12,6 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/unguessable_token.h" #include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "chromeos/ash/components/nearby/presence/conversions/proto_conversions.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom.h"
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h similarity index 96% rename from chrome/browser/nearby_sharing/nearby_connections_manager_impl.h rename to chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h index ea05494a..fb609018 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h +++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ -#define CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ +#ifndef CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_CONNECTIONS_MANAGER_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ +#define CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_CONNECTIONS_MANAGER_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ #include <memory> @@ -220,4 +220,4 @@ base::WeakPtrFactory<NearbyConnectionsManagerImpl> weak_ptr_factory_{this}; }; -#endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONNECTIONS_MANAGER_IMPL_H_ +#endif // CHROMEOS_ASH_COMPONENTS_NEARBY_COMMON_CONNECTIONS_MANAGER_NEARBY_CONNECTIONS_MANAGER_IMPL_H_
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc similarity index 99% rename from chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc rename to chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc index 02bebbb..629404f9 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc +++ b/chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/nearby_sharing/nearby_connections_manager_impl.h" +#include "chromeos/ash/components/nearby/common/connections_manager/nearby_connections_manager_impl.h" #include <algorithm> #include <memory>
diff --git a/chromeos/ash/components/nearby/presence/conversions/BUILD.gn b/chromeos/ash/components/nearby/presence/conversions/BUILD.gn index 06068cb..f57cf09 100644 --- a/chromeos/ash/components/nearby/presence/conversions/BUILD.gn +++ b/chromeos/ash/components/nearby/presence/conversions/BUILD.gn
@@ -9,6 +9,8 @@ static_library("conversions") { sources = [ + "nearby_presence_conversions.cc", + "nearby_presence_conversions.h", "proto_conversions.cc", "proto_conversions.h", ] @@ -25,6 +27,7 @@ "//third_party/nearby:connections_local_credential_proto", "//third_party/nearby:connections_metadata_proto", "//third_party/nearby:platform_api_comm", + "//third_party/nearby:presence_types", ] }
diff --git a/chrome/services/sharing/nearby/nearby_presence_conversions.cc b/chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.cc similarity index 98% rename from chrome/services/sharing/nearby/nearby_presence_conversions.cc rename to chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.cc index acaa603..646b1555 100644 --- a/chrome/services/sharing/nearby/nearby_presence_conversions.cc +++ b/chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/services/sharing/nearby/nearby_presence_conversions.h" +#include "chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h" #include "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom.h" #include "third_party/nearby/src/presence/data_element.h"
diff --git a/chrome/services/sharing/nearby/nearby_presence_conversions.h b/chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h similarity index 86% rename from chrome/services/sharing/nearby/nearby_presence_conversions.h rename to chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h index 91b5beba8..e8491499 100644 --- a/chrome/services/sharing/nearby/nearby_presence_conversions.h +++ b/chromeos/ash/components/nearby/presence/conversions/nearby_presence_conversions.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_SERVICES_SHARING_NEARBY_NEARBY_PRESENCE_CONVERSIONS_H_ -#define CHROME_SERVICES_SHARING_NEARBY_NEARBY_PRESENCE_CONVERSIONS_H_ +#ifndef CHROMEOS_ASH_COMPONENTS_NEARBY_PRESENCE_CONVERSIONS_NEARBY_PRESENCE_CONVERSIONS_H_ +#define CHROMEOS_ASH_COMPONENTS_NEARBY_PRESENCE_CONVERSIONS_NEARBY_PRESENCE_CONVERSIONS_H_ #include "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom-forward.h" #include "mojo/public/mojom/base/absl_status.mojom-forward.h" @@ -47,4 +47,4 @@ } // namespace ash::nearby::presence -#endif // CHROME_SERVICES_SHARING_NEARBY_NEARBY_PRESENCE_CONVERSIONS_H_ +#endif // CHROMEOS_ASH_COMPONENTS_NEARBY_PRESENCE_CONVERSIONS_NEARBY_PRESENCE_CONVERSIONS_H_
diff --git a/chromeos/ash/components/network/managed_network_configuration_handler_unittest.cc b/chromeos/ash/components/network/managed_network_configuration_handler_unittest.cc index e23253f..f7c0676 100644 --- a/chromeos/ash/components/network/managed_network_configuration_handler_unittest.cc +++ b/chromeos/ash/components/network/managed_network_configuration_handler_unittest.cc
@@ -2125,7 +2125,11 @@ } TEST_F(ManagedNetworkConfigurationHandlerTest, AllowApnModification) { - feature_list_.InitAndEnableFeature(features::kApnPolicies); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures(/*enabled_features=*/ + {features::kApnRevamp, + features::kApnPolicies}, + /*disabled_features=*/{}); // TODO(b/333100319): When feature is fully enabled, test // AllowApnModification() in other unit tests to be consistent.
diff --git a/chromeos/ash/components/quick_start/quick_start_metrics.cc b/chromeos/ash/components/quick_start/quick_start_metrics.cc index d0b4719e..399532f 100644 --- a/chromeos/ash/components/quick_start/quick_start_metrics.cc +++ b/chromeos/ash/components/quick_start/quick_start_metrics.cc
@@ -38,8 +38,25 @@ "QuickStart.FastPairAdvertisementEnded.Duration"; constexpr const char kFastPairAdvertisementEndedErrorCodeHistogramName[] = "QuickStart.FastPairAdvertisementEnded.ErrorCode"; -constexpr const char kFastPairAdvertisementStartedHistogramName[] = - "QuickStart.FastPairAdvertisementStarted"; +constexpr const char kFastPairAdvertisementStartedSucceededHistogramName[] = + "QuickStart.FastPairAdvertisementStarted.Succeeded"; +constexpr const char kFastPairAdvertisementStartedErrorCodeHistogramName[] = + "QuickStart.FastPairAdvertisementStarted.ErrorCode"; +constexpr const char + kNearbyConnectionsAdvertisementEndedSucceededHistogramName[] = + "QuickStart.NearbyConnectionsAdvertisementEnded.Succeeded"; +constexpr const char + kNearbyConnectionsAdvertisementEndedDurationHistogramName[] = + "QuickStart.NearbyConnectionsAdvertisementEnded.Duration"; +constexpr const char + kNearbyConnectionsAdvertisementEndedErrorCodeHistogramName[] = + "QuickStart.NearbyConnectionsAdvertisementEnded.ErrorCode"; +constexpr const char + kNearbyConnectionsAdvertisementStartedSucceededHistogramName[] = + "QuickStart.NearbyConnectionsAdvertisementStarted.Succeeded"; +constexpr const char + kNearbyConnectionsAdvertisementStartedErrorCodeHistogramName[] = + "QuickStart.NearbyConnectionsAdvertisementStarted.ErrorCode"; constexpr const char kAuthenticationMethodHistogramName[] = "QuickStart.AuthenticationMethod"; constexpr const char kMessageReceivedWifiCredentials[] = @@ -368,11 +385,22 @@ QuickStartMetrics::~QuickStartMetrics() = default; -void QuickStartMetrics::RecordFastPairAdvertisementStarted() { +void QuickStartMetrics::RecordFastPairAdvertisementStarted( + bool succeeded, + std::optional<FastPairAdvertisingErrorCode> error_code) { CHECK(!fast_pair_advertising_timer_); - fast_pair_advertising_timer_ = std::make_unique<base::ElapsedTimer>(); - base::UmaHistogramBoolean(kFastPairAdvertisementStartedHistogramName, true); + if (succeeded) { + CHECK(!error_code.has_value()); + fast_pair_advertising_timer_ = std::make_unique<base::ElapsedTimer>(); + } else { + CHECK(error_code.has_value()); + base::UmaHistogramEnumeration( + kFastPairAdvertisementStartedErrorCodeHistogramName, + error_code.value()); + } + base::UmaHistogramBoolean(kFastPairAdvertisementStartedSucceededHistogramName, + succeeded); } void QuickStartMetrics::RecordFastPairAdvertisementEnded( @@ -384,6 +412,8 @@ if (succeeded) { CHECK(!error_code.has_value()); + base::UmaHistogramTimes(kFastPairAdvertisementEndedDurationHistogramName, + duration); } else { CHECK(error_code.has_value()); base::UmaHistogramEnumeration( @@ -391,20 +421,51 @@ } base::UmaHistogramBoolean(kFastPairAdvertisementEndedSucceededHistogramName, succeeded); - base::UmaHistogramTimes(kFastPairAdvertisementEndedDurationHistogramName, - duration); fast_pair_advertising_timer_.reset(); } -void QuickStartMetrics::RecordNearbyConnectionsAdvertisementStarted() { - // TODO(b/279614071): Add advertising metrics. +void QuickStartMetrics::RecordNearbyConnectionsAdvertisementStarted( + bool succeeded, + std::optional<NearbyConnectionsAdvertisingErrorCode> error_code) { + CHECK(!nearby_connections_advertising_timer_); + + if (succeeded) { + CHECK(!error_code.has_value()); + nearby_connections_advertising_timer_ = + std::make_unique<base::ElapsedTimer>(); + } else { + CHECK(error_code.has_value()); + base::UmaHistogramEnumeration( + kNearbyConnectionsAdvertisementStartedErrorCodeHistogramName, + error_code.value()); + } + + base::UmaHistogramBoolean( + kNearbyConnectionsAdvertisementStartedSucceededHistogramName, succeeded); } void QuickStartMetrics::RecordNearbyConnectionsAdvertisementEnded( bool succeeded, std::optional<NearbyConnectionsAdvertisingErrorCode> error_code) { - // TODO(b/279614071): Add advertising metrics. + CHECK(nearby_connections_advertising_timer_); + + base::TimeDelta duration = nearby_connections_advertising_timer_->Elapsed(); + + if (succeeded) { + CHECK(!error_code.has_value()); + base::UmaHistogramTimes( + kNearbyConnectionsAdvertisementEndedDurationHistogramName, duration); + } else { + CHECK(error_code.has_value()); + base::UmaHistogramEnumeration( + kNearbyConnectionsAdvertisementEndedErrorCodeHistogramName, + error_code.value()); + } + base::UmaHistogramBoolean( + kNearbyConnectionsAdvertisementEndedSucceededHistogramName, succeeded); + + nearby_connections_advertising_timer_.reset(); } void QuickStartMetrics::RecordHandshakeStarted() {
diff --git a/chromeos/ash/components/quick_start/quick_start_metrics.h b/chromeos/ash/components/quick_start/quick_start_metrics.h index 2bb8951c..61ae608a 100644 --- a/chromeos/ash/components/quick_start/quick_start_metrics.h +++ b/chromeos/ash/components/quick_start/quick_start_metrics.h
@@ -86,9 +86,10 @@ // This enum is tied directly to a UMA enum defined in // //tools/metrics/histograms/metadata/quickstart/enums.xml and should always - // reflect it. The UMA enum cannot use - // |device::BluetoothAdvertisement::ErrorCode| directly, because it is missing - // the required |kMaxValue| field. + // reflect it (do not change one without changing the other). Entries should + // be never modified or deleted. Only additions possible. The UMA enum cannot + // use |device::BluetoothAdvertisement::ErrorCode| directly, because it is + // missing the required |kMaxValue| field. enum class FastPairAdvertisingErrorCode { kUnsupportedPlatform = 0, kAdvertisementAlreadyExists = 1, @@ -102,8 +103,21 @@ kMaxValue = kInvalidAdvertisementErrorCode, }; + // This enum is tied directly to a UMA enum defined in + // //tools/metrics/histograms/metadata/quickstart/enums.xml and should always + // reflect it (do not change one without changing the other). Entries should + // be never modified or deleted. Only additions possible. enum class NearbyConnectionsAdvertisingErrorCode { - kFailedToStart, + kError = 0, + kOutOfOrderApiCall = 1, + kAlreadyHaveActiveStrategy = 2, + kAlreadyAdvertising = 3, + kBluetoothError = 4, + kBleError = 5, + kUnknown = 6, + kTimeout = 7, + kOther = 8, + kMaxValue = kOther, }; // This enum is tied directly to a UMA enum defined in @@ -276,13 +290,17 @@ void RecordGaiaAuthenticationRequestEnded( const GaiaAuthenticationResult& result); - void RecordFastPairAdvertisementStarted(); + void RecordFastPairAdvertisementStarted( + bool succeeded, + std::optional<FastPairAdvertisingErrorCode> error_code); void RecordFastPairAdvertisementEnded( bool succeeded, std::optional<FastPairAdvertisingErrorCode> error_code); - void RecordNearbyConnectionsAdvertisementStarted(); + void RecordNearbyConnectionsAdvertisementStarted( + bool succeeded, + std::optional<NearbyConnectionsAdvertisingErrorCode> error_code); void RecordNearbyConnectionsAdvertisementEnded( bool succeeded, @@ -307,6 +325,14 @@ // finishes. std::unique_ptr<base::ElapsedTimer> fast_pair_advertising_timer_; + // Timer to keep track of Nearby Connections advertising duration. Should be + // constructed when advertising starts and destroyed when advertising + // finishes. + std::unique_ptr<base::ElapsedTimer> nearby_connections_advertising_timer_; + + // Timer to keep track of duration spent viewing a screen. Should be + // constructed when a screen is opened and destroyed when that screen is + // closed. std::unique_ptr<base::ElapsedTimer> screen_opened_view_duration_timer_; // Timer to keep track of handshake duration. Should be constructed when
diff --git a/chromeos/ash/components/report/device_metrics/actives/one_day_impl.cc b/chromeos/ash/components/report/device_metrics/actives/one_day_impl.cc index b0cd37e2..1c8000e 100644 --- a/chromeos/ash/components/report/device_metrics/actives/one_day_impl.cc +++ b/chromeos/ash/components/report/device_metrics/actives/one_day_impl.cc
@@ -380,7 +380,7 @@ GetParams()->GetChromeDeviceParams().market_segment; DeviceMetadata* device_metadata = import_request.mutable_device_metadata(); - device_metadata->set_chromeos_version(utils::GetChromeMilestone()); + device_metadata->set_chrome_milestone(utils::GetChromeMilestone()); device_metadata->set_hardware_id(utils::GetFullHardwareClass()); device_metadata->set_chromeos_channel( utils::GetChromeChannel(version_channel));
diff --git a/chromeos/ash/components/report/device_metrics/actives/twenty_eight_day_impl.cc b/chromeos/ash/components/report/device_metrics/actives/twenty_eight_day_impl.cc index 9976966..9c4583b 100644 --- a/chromeos/ash/components/report/device_metrics/actives/twenty_eight_day_impl.cc +++ b/chromeos/ash/components/report/device_metrics/actives/twenty_eight_day_impl.cc
@@ -179,7 +179,7 @@ GetParams()->GetChromeDeviceParams().market_segment; DeviceMetadata* device_metadata = import_request.mutable_device_metadata(); - device_metadata->set_chromeos_version(utils::GetChromeMilestone()); + device_metadata->set_chrome_milestone(utils::GetChromeMilestone()); device_metadata->set_hardware_id(utils::GetFullHardwareClass()); device_metadata->set_chromeos_channel( utils::GetChromeChannel(version_channel));
diff --git a/chromeos/ash/components/report/device_metrics/churn/cohort_impl.cc b/chromeos/ash/components/report/device_metrics/churn/cohort_impl.cc index cc647d0f..9273f30d 100644 --- a/chromeos/ash/components/report/device_metrics/churn/cohort_impl.cc +++ b/chromeos/ash/components/report/device_metrics/churn/cohort_impl.cc
@@ -323,7 +323,7 @@ GetParams()->GetChromeDeviceParams().market_segment; DeviceMetadata* device_metadata = import_request.mutable_device_metadata(); - device_metadata->set_chromeos_version(utils::GetChromeMilestone()); + device_metadata->set_chrome_milestone(utils::GetChromeMilestone()); device_metadata->set_hardware_id(utils::GetFullHardwareClass()); device_metadata->set_chromeos_channel( utils::GetChromeChannel(version_channel));
diff --git a/chromeos/ash/components/report/device_metrics/churn/observation_impl.cc b/chromeos/ash/components/report/device_metrics/churn/observation_impl.cc index 2b3d6ca..d34d93e 100644 --- a/chromeos/ash/components/report/device_metrics/churn/observation_impl.cc +++ b/chromeos/ash/components/report/device_metrics/churn/observation_impl.cc
@@ -334,7 +334,7 @@ GetParams()->GetChromeDeviceParams().market_segment; DeviceMetadata* device_metadata = import_request.mutable_device_metadata(); - device_metadata->set_chromeos_version(utils::GetChromeMilestone()); + device_metadata->set_chrome_milestone(utils::GetChromeMilestone()); device_metadata->set_hardware_id(utils::GetFullHardwareClass()); device_metadata->set_chromeos_channel( utils::GetChromeChannel(version_channel));
diff --git a/chromeos/ash/components/report/proto/fresnel_service.proto b/chromeos/ash/components/report/proto/fresnel_service.proto index 09475fbf..4420506 100644 --- a/chromeos/ash/components/report/proto/fresnel_service.proto +++ b/chromeos/ash/components/report/proto/fresnel_service.proto
@@ -51,10 +51,10 @@ // See: go/gvc-g3/logs/chromeos-metrics.md optional string hardware_id = 1; - // Represent the current release milestone of the ChromeOS device. + // Represent the Chrome major milestone of the ChromeOS device. // See chrome://version -> Google Chrome: // i.e. 96.0.4664.55 (Official Build) (x86_64) would set field as "96". - optional string chromeos_version = 2; + optional string chrome_milestone = 2; // Country code is represented by a 2-letter string (aka ISO 3166-1). // i.e. US for United States of America, CA for Canada. @@ -66,7 +66,7 @@ // ChromeOS channel is used to determine the breakdown of devices that are // coming from canary, dev, beta, stable, or unknown channels. - // This can be used with the ChromeOS version in order to determine + // This can be used with the chrome milestone in order to determine // questions like, what percentage of devices are in the M100 stable channel. optional Channel chromeos_channel = 5; }
diff --git a/chromeos/ash/components/report/utils/device_metadata_utils.h b/chromeos/ash/components/report/utils/device_metadata_utils.h index 9fa1e06..b6c01502b 100644 --- a/chromeos/ash/components/report/utils/device_metadata_utils.h +++ b/chromeos/ash/components/report/utils/device_metadata_utils.h
@@ -18,7 +18,7 @@ // Return the release Chrome Channel enum defined in fresnel service proto. ash::report::Channel GetChromeChannel(version_info::Channel channel); -// Retrieve the release Chrome Milestone as a string. +// Retrieve the major Chrome Milestone of the ChromeOS device as a string. std::string GetChromeMilestone(); // Retrieve full hardware class from MachineStatistics as a string.
diff --git a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.cc b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.cc index c0256c22..f0e9b36 100644 --- a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.cc +++ b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.cc
@@ -98,7 +98,11 @@ WifiP2PController::WifiP2PController() = default; -WifiP2PController::~WifiP2PController() = default; +WifiP2PController::~WifiP2PController() { + if (ShillManagerClient::Get()) { + ShillManagerClient::Get()->RemovePropertyChangedObserver(this); + } +} void WifiP2PController::Init() { ShillManagerClient::Get()->SetProperty( @@ -107,6 +111,11 @@ base::BindOnce(&WifiP2PController::OnSetManagerPropertyFailure, weak_ptr_factory_.GetWeakPtr(), shill::kP2PAllowedProperty)); + + ShillManagerClient::Get()->AddPropertyChangedObserver(this); + ShillManagerClient::Get()->GetProperties( + base::BindOnce(&WifiP2PController::OnGetManagerProperties, + weak_ptr_factory_.GetWeakPtr())); } void WifiP2PController::OnSetManagerPropertyFailure( @@ -304,4 +313,54 @@ std::move(callback_split.second))); } +const WifiP2PController::WifiP2PCapabilities& +WifiP2PController::GetP2PCapabilities() const { + return wifi_p2p_capabilities_; +} + +void WifiP2PController::OnPropertyChanged(const std::string& key, + const base::Value& value) { + if (key == shill::kP2PCapabilitiesProperty) { + NET_LOG(EVENT) << "WifiP2PController: Registered a property change event " + "on kP2PCapabilitiesProperty"; + UpdateP2PCapabilities(value.GetDict()); + } +} + +void WifiP2PController::OnGetManagerProperties( + std::optional<base::Value::Dict> properties) { + if (!properties) { + NET_LOG(ERROR) + << "WifiP2PController: Failed to get shill manager properties."; + return; + } + const base::Value::Dict* value = + properties->FindDict(shill::kP2PCapabilitiesProperty); + if (!value) { + NET_LOG(ERROR) << "WifiP2PController: No dictionary value for: " + << shill::kP2PCapabilitiesProperty; + return; + } + + UpdateP2PCapabilities(*value); +} + +void WifiP2PController::UpdateP2PCapabilities( + const base::Value::Dict& capabilities) { + const std::string* group_readiness = + capabilities.FindString(shill::kP2PCapabilitiesGroupReadinessProperty); + const std::string* client_readiness = + capabilities.FindString(shill::kP2PCapabilitiesClientReadinessProperty); + + if (group_readiness) { + wifi_p2p_capabilities_.is_owner_ready = + (*group_readiness == shill::kP2PCapabilitiesGroupReadinessReady); + } + + if (client_readiness) { + wifi_p2p_capabilities_.is_client_ready = + (*client_readiness == shill::kP2PCapabilitiesClientReadinessReady); + } +} + } // namespace ash
diff --git a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.h b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.h index e8dce8b..b2d2d11 100644 --- a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.h +++ b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" #include "base/values.h" +#include "chromeos/ash/components/dbus/shill/shill_property_changed_observer.h" namespace ash { @@ -22,7 +23,8 @@ // 4. Disconnect from a p2p group // 5. Fetch p2p group/client properties // 6. Tag socket to a WiFi direct group network rules. -class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_WIFI_P2P) WifiP2PController { +class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_WIFI_P2P) WifiP2PController + : public ShillPropertyChangedObserver { public: // Sets the global instance. Must be called before any calls to Get(). static void Initialize(); @@ -46,6 +48,21 @@ int network_id; }; + struct WifiP2PCapabilities { + WifiP2PCapabilities(const bool is_owner_ready, const bool is_client_ready) + : is_owner_ready(is_owner_ready), is_client_ready(is_client_ready) {} + + ~WifiP2PCapabilities() = default; + + // Whether platform is ready for creating p2p GO interface without any + // concurrency conflict. + bool is_owner_ready; + + // Whether platform is ready for creating p2p GC interface without any + // concurrency conflict. + bool is_client_ready; + }; + enum OperationResult { kSuccess, // Wifi direct is disallowed in platform per Manager.P2PAllowed. @@ -98,14 +115,22 @@ std::optional<uint32_t> frequency, WifiP2PGroupCallback callback); + void OnGetManagerProperties(std::optional<base::Value::Dict> properties); + + const WifiP2PCapabilities& GetP2PCapabilities() const; + private: WifiP2PController(); WifiP2PController(const WifiP2PController&) = delete; WifiP2PController& operator=(const WifiP2PController&) = delete; - ~WifiP2PController(); + ~WifiP2PController() override; void Init(); + // ShillPropertyChangedObserver overrides + void OnPropertyChanged(const std::string& key, + const base::Value& value) override; + void OnCreateOrConnectP2PGroupSuccess(bool create_group, WifiP2PGroupCallback callback, base::Value::Dict result); @@ -123,6 +148,10 @@ const std::string& error_name, const std::string& error_message); + void UpdateP2PCapabilities(const base::Value::Dict& capabilities); + + WifiP2PCapabilities wifi_p2p_capabilities_{false, false}; + base::WeakPtrFactory<WifiP2PController> weak_ptr_factory_{this}; };
diff --git a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller_unittest.cc b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller_unittest.cc index 3982f83..65d28a7 100644 --- a/chromeos/ash/components/wifi_p2p/wifi_p2p_controller_unittest.cc +++ b/chromeos/ash/components/wifi_p2p/wifi_p2p_controller_unittest.cc
@@ -205,4 +205,31 @@ WifiP2PController::Shutdown(); } +TEST_F(WifiP2PControllerTest, GetP2PCapabilities) { + auto capabilities_dict = + base::Value::Dict().Set(shill::kP2PCapabilitiesGroupReadinessProperty, + shill::kP2PCapabilitiesGroupReadinessReady); + capabilities_dict.Set(shill::kP2PCapabilitiesClientReadinessProperty, + shill::kP2PCapabilitiesClientReadinessReady); + ShillManagerClient::Get()->GetTestInterface()->SetManagerProperty( + shill::kP2PCapabilitiesProperty, base::Value(capabilities_dict.Clone())); + + Init(); + + WifiP2PController::WifiP2PCapabilities result = + WifiP2PController::Get()->GetP2PCapabilities(); + EXPECT_TRUE(result.is_owner_ready); + EXPECT_TRUE(result.is_client_ready); + + capabilities_dict.Set(shill::kP2PCapabilitiesClientReadinessProperty, + shill::kP2PCapabilitiesClientReadinessNotReady); + ShillManagerClient::Get()->GetTestInterface()->SetManagerProperty( + shill::kP2PCapabilitiesProperty, base::Value(capabilities_dict.Clone())); + base::RunLoop().RunUntilIdle(); + + result = WifiP2PController::Get()->GetP2PCapabilities(); + EXPECT_TRUE(result.is_owner_ready); + EXPECT_FALSE(result.is_client_ready); +} + } // namespace ash
diff --git a/chromeos/ash/resources/internal b/chromeos/ash/resources/internal index a58ffb4..3a96117 160000 --- a/chromeos/ash/resources/internal +++ b/chromeos/ash/resources/internal
@@ -1 +1 @@ -Subproject commit a58ffb4694b2b0be123300e533578ed96aabcb5a +Subproject commit 3a961174a24cfda9e444f54e3f1c783f75838b41
diff --git a/chromeos/ash/services/network_config/cros_network_config_unittest.cc b/chromeos/ash/services/network_config/cros_network_config_unittest.cc index e2bd0f3..4867eae 100644 --- a/chromeos/ash/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/ash/services/network_config/cros_network_config_unittest.cc
@@ -4208,7 +4208,14 @@ EXPECT_EQ(1, observer()->GetPolicyAppliedCount(/*userhash=*/std::string())); - feature_list.InitAndEnableFeature(features::kApnPolicies); + policy = GetGlobalPolicy(); + EXPECT_TRUE(policy->allow_apn_modification); + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures(/*enabled_features=*/ + {features::kApnRevamp, + features::kApnPolicies}, + /*disabled_features=*/{}); policy = GetGlobalPolicy(); EXPECT_FALSE(policy->allow_apn_modification); }
diff --git a/clank b/clank index bce8895..4799cd3 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit bce889557aaf353bc3e2b00592df54a5fc4d0db0 +Subproject commit 4799cd305fe7062e4a6e9b455b2bb2c4db50060d
diff --git a/components/BUILD.gn b/components/BUILD.gn index 508c1d22b..a1be8620 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -711,6 +711,7 @@ if (is_chromeos_ash) { deps += [ "//components/arc:unit_tests", + "//components/cross_device/nearby:unit_tests", "//components/desks_storage:unit_tests", "//components/guest_os:unit_tests", "//components/ownership:unit_tests",
diff --git a/components/android_autofill/browser/form_data_android_unittest.cc b/components/android_autofill/browser/form_data_android_unittest.cc index 22537d7..486b674 100644 --- a/components/android_autofill/browser/form_data_android_unittest.cc +++ b/components/android_autofill/browser/form_data_android_unittest.cc
@@ -50,8 +50,8 @@ static uint64_t renderer_id = 1; FormFieldData f; f.set_name(std::move(name)); - f.name_attribute = f.name(); - f.id_attribute = u"some_id"; + f.set_name_attribute(f.name()); + f.set_id_attribute(u"some_id"); f.set_form_control_type(FormControlType::kInputText); f.check_status = FormFieldData::CheckStatus::kChecked; f.role = FormFieldData::RoleAttribute::kOther;
diff --git a/components/android_autofill/browser/form_field_data_android.cc b/components/android_autofill/browser/form_field_data_android.cc index e21edba..5537c580 100644 --- a/components/android_autofill/browser/form_field_data_android.cc +++ b/components/android_autofill/browser/form_field_data_android.cc
@@ -87,8 +87,8 @@ bool FormFieldDataAndroid::SimilarFieldAs(const FormFieldData& field) const { auto SimilarityTuple = [](const FormFieldData& f) { return std::tuple_cat( - std::tie(f.host_frame, f.renderer_id(), f.name(), f.name_attribute, - f.id_attribute, f.form_control_type()), + std::tie(f.host_frame, f.renderer_id(), f.name(), f.name_attribute(), + f.id_attribute(), f.form_control_type()), std::make_tuple(IsCheckable(f.check_status))); };
diff --git a/components/android_autofill/browser/form_field_data_android_bridge_impl.cc b/components/android_autofill/browser/form_field_data_android_bridge_impl.cc index bf42379..47315bd2 100644 --- a/components/android_autofill/browser/form_field_data_android_bridge_impl.cc +++ b/components/android_autofill/browser/form_field_data_android_bridge_impl.cc
@@ -77,7 +77,7 @@ ConvertUTF16ToJavaString(env, field.placeholder), ConvertUTF8ToJavaString( env, FormControlTypeToString(field.form_control_type())), - ConvertUTF16ToJavaString(env, field.id_attribute), + ConvertUTF16ToJavaString(env, field.id_attribute()), /*optionValues=*/ProjectOptions(field.options, &SelectOption::value), /*optionContents=*/ProjectOptions(field.options, &SelectOption::content), IsCheckable(field.check_status), IsChecked(field.check_status),
diff --git a/components/android_autofill/browser/form_field_data_android_unittest.cc b/components/android_autofill/browser/form_field_data_android_unittest.cc index 41cf656..60422103 100644 --- a/components/android_autofill/browser/form_field_data_android_unittest.cc +++ b/components/android_autofill/browser/form_field_data_android_unittest.cc
@@ -22,8 +22,8 @@ FormFieldData CreateTestField() { FormFieldData f; f.set_name(u"SomeName"); - f.name_attribute = f.name(); - f.id_attribute = u"some_id"; + f.set_name_attribute(f.name()); + f.set_id_attribute(u"some_id"); f.set_form_control_type(FormControlType::kInputText); f.check_status = FormFieldData::CheckStatus::kChecked; return f; @@ -154,12 +154,12 @@ // If name attributes differ, they are not similar. f2 = f1; - f2.name_attribute = f1.name_attribute + u"x"; + f2.set_name_attribute(f1.name_attribute() + u"x"); EXPECT_FALSE(af.SimilarFieldAs(f2)); // If id attributes differ, they are not similar. f2 = f1; - f2.id_attribute = f1.id_attribute + u"x"; + f2.set_id_attribute(f1.id_attribute() + u"x"); EXPECT_FALSE(af.SimilarFieldAs(f2)); // If form control types differ, they are not similar.
diff --git a/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc b/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc index c0c212c08..4ccd80e 100644 --- a/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc +++ b/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc
@@ -82,7 +82,7 @@ FormData formData = j.second->ToFormData(); for (size_t i = 0; i < field_ids.size(); ++i) { for (auto form_field_data : formData.fields) { - if (form_field_data.id_attribute == field_ids[i]) { + if (form_field_data.id_attribute() == field_ids[i]) { autofill::test::AddFieldPredictionToForm( form_field_data, static_cast<autofill::FieldType>(raw_field_types[i]), @@ -136,7 +136,7 @@ FormData formData = j.second->ToFormData(); for (size_t i = 0; i < field_ids.size(); ++i) { for (auto form_field_data : formData.fields) { - if (form_field_data.id_attribute == field_ids[i]) { + if (form_field_data.id_attribute() == field_ids[i]) { std::vector<FieldType> field_types; field_types.reserve(raw_field_types[i].size()); base::ranges::transform(
diff --git a/components/autofill/content/renderer/autofill_agent_browsertest.cc b/components/autofill/content/renderer/autofill_agent_browsertest.cc index 36ff8c3..e6de44a 100644 --- a/components/autofill/content/renderer/autofill_agent_browsertest.cc +++ b/components/autofill/content/renderer/autofill_agent_browsertest.cc
@@ -91,7 +91,7 @@ std::vector<Matcher<FormFieldData>> field_matchers; for (std::u16string& id_attribute : id_attributes) { field_matchers.push_back( - Field(&FormFieldData::id_attribute, std::move(id_attribute))); + Property(&FormFieldData::id_attribute, std::move(id_attribute))); } return Field(&FormData::fields, ElementsAreArray(field_matchers)); } @@ -1035,7 +1035,7 @@ } for (FormFieldData& field : form->fields) { - field.set_value(field.id_attribute + u" autofilled"); + field.set_value(field.id_attribute() + u" autofilled"); field.is_autofilled = true; }
diff --git a/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc b/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc index 26e04008..e3a9429 100644 --- a/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc +++ b/components/autofill/content/renderer/autofill_agent_form_interaction_browsertest.cc
@@ -38,7 +38,7 @@ // Returns a matcher that matches a `FormFieldData::id_attribute`. auto HasFieldIdAttribute(std::u16string id_attribute) { - return Field("id_attribute", &FormFieldData::id_attribute, id_attribute); + return Property("id_attribute", &FormFieldData::id_attribute, id_attribute); } // Returns a matcher that matches a `FormFieldData::form_control_type`.
diff --git a/components/autofill/content/renderer/form_autofill_issues.cc b/components/autofill/content/renderer/form_autofill_issues.cc index e5f9aa1a..6c23779 100644 --- a/components/autofill/content/renderer/form_autofill_issues.cc +++ b/components/autofill/content/renderer/form_autofill_issues.cc
@@ -275,7 +275,7 @@ std::set<std::u16string> elements_whose_name_match_a_label_for_attr; for (const FormFieldData& field : fields) { if (field.label_source == FormFieldData::LabelSource::kForName) { - elements_whose_name_match_a_label_for_attr.insert(field.name_attribute); + elements_whose_name_match_a_label_for_attr.insert(field.name_attribute()); } }
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index 98d615b..b915ae39 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1924,8 +1924,8 @@ // Save both id and name attributes, if present. If there is only one of them, // it will be saved to |name|. See HTMLFormControlElement::nameForAutofill. field->set_name(element.NameForAutofill().Utf16()); - field->id_attribute = element.GetIdAttribute().Utf16(); - field->name_attribute = GetAttribute<kName>(element).Utf16(); + field->set_id_attribute(element.GetIdAttribute().Utf16()); + field->set_name_attribute(GetAttribute<kName>(element).Utf16()); field->set_renderer_id(renderer_id); field->host_form_id = GetFormRendererId(form_element); field->form_control_ax_id = element.GetAxId(); @@ -1975,13 +1975,16 @@ if (shadow_data && !shadow_host_name.empty()) shadow_data->shadow_host_name_attributes.push_back(shadow_host_name); - if (field->id_attribute.empty()) - field->id_attribute = host.GetIdAttribute().Utf16(); - if (field->name_attribute.empty()) - field->name_attribute = GetAttribute<kName>(host).Utf16(); + if (field->id_attribute().empty()) { + field->set_id_attribute(host.GetIdAttribute().Utf16()); + } + if (field->name_attribute().empty()) { + field->set_name_attribute(GetAttribute<kName>(host).Utf16()); + } if (field->name().empty()) { - field->set_name(field->name_attribute.empty() ? field->id_attribute - : field->name_attribute); + field->set_name(field->name_attribute().empty() + ? field->id_attribute() + : field->name_attribute()); } if (field->autocomplete_attribute.empty()) { field->autocomplete_attribute = GetAutocompleteAttribute(host); @@ -2182,10 +2185,10 @@ FormFieldData& field = form.fields.back(); WebDocument document = content_editable.GetDocument(); - field.id_attribute = content_editable.GetIdAttribute().Utf16(); - field.name_attribute = GetAttribute<kName>(content_editable).Utf16(); - field.set_name(!field.id_attribute.empty() ? field.id_attribute - : field.name_attribute); + field.set_id_attribute(content_editable.GetIdAttribute().Utf16()); + field.set_name_attribute(GetAttribute<kName>(content_editable).Utf16()); + field.set_name(!field.id_attribute().empty() ? field.id_attribute() + : field.name_attribute()); field.set_renderer_id(GetFieldRendererId(content_editable)); field.host_form_id = GetFormRendererId(content_editable); field.set_form_control_type(FormControlType::kContentEditable);
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc index 111ea23..31ced72 100644 --- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc +++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -228,8 +228,8 @@ EXPECT_EQ(form_data.name_attribute, u"form-name"); ASSERT_EQ(form_data.fields.size(), 1u); EXPECT_EQ(form_data.fields[0].name(), u"input-name"); - EXPECT_EQ(form_data.fields[0].id_attribute, u"input-id"); - EXPECT_EQ(form_data.fields[0].name_attribute, u"input-name"); + EXPECT_EQ(form_data.fields[0].id_attribute(), u"input-id"); + EXPECT_EQ(form_data.fields[0].name_attribute(), u"input-name"); } // Tests that large option values/contents are truncated while building the @@ -1940,8 +1940,8 @@ EXPECT_EQ(form->renderer_id, field.host_form_id); EXPECT_EQ(field.parsed_autocomplete->field_type, HtmlFieldType::kGivenName); EXPECT_EQ(field.name(), u"my-id"); - EXPECT_EQ(field.id_attribute, u"my-id"); - EXPECT_EQ(field.name_attribute, u"my-name"); + EXPECT_EQ(field.id_attribute(), u"my-id"); + EXPECT_EQ(field.name_attribute(), u"my-name"); EXPECT_EQ(field.css_classes, u"my-class"); EXPECT_EQ(field.value(), u"\n This is the textContent!\n "); @@ -1968,8 +1968,8 @@ EXPECT_EQ(form->renderer_id, field.host_form_id); EXPECT_EQ(field.parsed_autocomplete->field_type, HtmlFieldType::kGivenName); EXPECT_EQ(field.name(), u"my-id"); - EXPECT_EQ(field.id_attribute, u"my-id"); - EXPECT_EQ(field.name_attribute, u"my-name"); + EXPECT_EQ(field.id_attribute(), u"my-id"); + EXPECT_EQ(field.name_attribute(), u"my-name"); EXPECT_EQ(field.css_classes, u"my-class"); // Only extract 1024 characters from the div. EXPECT_EQ(field.value().length(), 1024u);
diff --git a/components/autofill/content/renderer/html_based_username_detector.cc b/components/autofill/content/renderer/html_based_username_detector.cc index 57edf72..7219f29 100644 --- a/components/autofill/content/renderer/html_based_username_detector.cc +++ b/components/autofill/content/renderer/html_based_username_detector.cc
@@ -108,7 +108,7 @@ AppendValueAndShortTokens(field.name(), &field_data.developer_value, &field_data.developer_short_tokens); - AppendValueAndShortTokens(field.id_attribute, &field_data.developer_value, + AppendValueAndShortTokens(field.id_attribute(), &field_data.developer_value, &field_data.developer_short_tokens); AppendValueAndShortTokens(field.label(), &field_data.user_value, &field_data.user_short_tokens);
diff --git a/components/autofill/core/browser/autofill_feedback_data.cc b/components/autofill/core/browser/autofill_feedback_data.cc index d43022a8..57bcdd0 100644 --- a/components/autofill/core/browser/autofill_feedback_data.cc +++ b/components/autofill/core/browser/autofill_feedback_data.cc
@@ -38,8 +38,8 @@ base::NumberToString(field->GetFieldSignature().value())); field_data.Set("hostFormSignature", base::NumberToString(field->host_form_signature.value())); - field_data.Set("idAttribute", field->id_attribute); - field_data.Set("parseableNameAttribute", field->name_attribute); + field_data.Set("idAttribute", field->id_attribute()); + field_data.Set("parseableNameAttribute", field->name_attribute()); field_data.Set("autocompleteAttribute", field->autocomplete_attribute); field_data.Set("labelAttribute", field->label()); field_data.Set("placeholderAttribute", field->placeholder);
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc index 0b0da5c..609a466 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -250,14 +250,14 @@ AutofillRandomizedFieldMetadata* metadata) { const FormSignature form_signature = form.form_signature(); const FieldSignature field_signature = field.GetFieldSignature(); - if (!field.id_attribute.empty()) { + if (!field.id_attribute().empty()) { EncodeRandomizedValue(encoder, form_signature, field_signature, - RandomizedEncoder::FIELD_ID, field.id_attribute, + RandomizedEncoder::FIELD_ID, field.id_attribute(), /*include_checksum=*/false, metadata->mutable_id()); } - if (!field.name_attribute.empty()) { + if (!field.name_attribute().empty()) { EncodeRandomizedValue(encoder, form_signature, field_signature, - RandomizedEncoder::FIELD_NAME, field.name_attribute, + RandomizedEncoder::FIELD_NAME, field.name_attribute(), /*include_checksum=*/false, metadata->mutable_name()); } EncodeRandomizedValue(encoder, form_signature, field_signature,
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc index fca348e6..388d0c78 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
@@ -446,16 +446,16 @@ form.fields.push_back(CreateTestFormField("First Name", "firstname", "", FormControlType::kInputText, "given-name")); - form.fields.back().name_attribute = form.fields.back().name(); - form.fields.back().id_attribute = u"first_name"; + form.fields.back().set_name_attribute(form.fields.back().name()); + form.fields.back().set_id_attribute(u"first_name"); form.fields.back().css_classes = u"class1 class2"; form.fields.back().properties_mask = FieldPropertiesFlags::kHadFocus; test::InitializePossibleTypes(possible_field_types, {NAME_FIRST}); form.fields.push_back(CreateTestFormField( "Last Name", "lastname", "", FormControlType::kInputText, "family-name")); - form.fields.back().name_attribute = form.fields.back().name(); - form.fields.back().id_attribute = u"last_name"; + form.fields.back().set_name_attribute(form.fields.back().name()); + form.fields.back().set_id_attribute(u"last_name"); form.fields.back().css_classes = u"class1 class2"; form.fields.back().properties_mask = FieldPropertiesFlags::kHadFocus | FieldPropertiesFlags::kUserTyped; @@ -463,8 +463,8 @@ form.fields.push_back(CreateTestFormField( "Email", "email", "", FormControlType::kInputEmail, "email")); - form.fields.back().name_attribute = form.fields.back().name(); - form.fields.back().id_attribute = u"e-mail"; + form.fields.back().set_name_attribute(form.fields.back().name()); + form.fields.back().set_id_attribute(u"e-mail"); form.fields.back().css_classes = u"class1 class2"; form.fields.back().properties_mask = FieldPropertiesFlags::kHadFocus | FieldPropertiesFlags::kUserTyped; @@ -1181,9 +1181,9 @@ form.full_url = GURL("http://www.foo.com/?foo=bar"); for (const auto& f : kFieldMetadata) { FormFieldData field; - field.id_attribute = ASCIIToUTF16(f.id); - field.name_attribute = ASCIIToUTF16(f.name); - field.set_name(field.name_attribute); + field.set_id_attribute(ASCIIToUTF16(f.id)); + field.set_name_attribute(ASCIIToUTF16(f.name)); + field.set_name(field.name_attribute()); field.set_label(ASCIIToUTF16(f.label)); field.placeholder = ASCIIToUTF16(f.placeholder); field.aria_label = ASCIIToUTF16(f.aria_label); @@ -1253,13 +1253,13 @@ const auto& metadata = upload.field(i).randomized_field_metadata(); const auto& field = *form_structure.field(i); const auto field_signature = field.GetFieldSignature(); - if (field.id_attribute.empty()) { + if (field.id_attribute().empty()) { EXPECT_FALSE(metadata.has_id()); } else { EXPECT_EQ(metadata.id().encoded_bits(), encoder.EncodeForTesting(form_signature, field_signature, RandomizedEncoder::FIELD_ID, - field.id_attribute)); + field.id_attribute())); } if (field.name().empty()) { EXPECT_FALSE(metadata.has_name()); @@ -1267,7 +1267,7 @@ EXPECT_EQ(metadata.name().encoded_bits(), encoder.EncodeForTesting(form_signature, field_signature, RandomizedEncoder::FIELD_NAME, - field.name_attribute)); + field.name_attribute())); } EXPECT_EQ( metadata.type().encoded_bits(),
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc index 8f1196c..5b06de76 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_manager_unittest.cc
@@ -1483,9 +1483,9 @@ // Add field 0. FormFieldData field; - field.id_attribute = u"field-id-attribute-1"; - field.name_attribute = u"field-name-attribute-1"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-1"); + field.set_name_attribute(u"field-name-attribute-1"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-description"; @@ -1495,9 +1495,9 @@ form.fields.push_back(field); // Add field 1. - field.id_attribute = u"field-id-attribute-2"; - field.name_attribute = u"field-name-attribute-2"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-2"); + field.set_name_attribute(u"field-name-attribute-2"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-description"; @@ -1507,9 +1507,9 @@ form.fields.push_back(field); // Add field 2. - field.id_attribute = u"field-id-attribute-3"; - field.name_attribute = u"field-name-attribute-3"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-3"); + field.set_name_attribute(u"field-name-attribute-3"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-description"; @@ -1570,9 +1570,9 @@ form.name = form.name_attribute; FormFieldData field; - field.id_attribute = u"field-id-attribute-1"; - field.name_attribute = u"field-name-attribute-1"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-1"); + field.set_name_attribute(u"field-name-attribute-1"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-descriptionm"; @@ -1581,9 +1581,9 @@ field.placeholder = u"field-placeholder"; form.fields.push_back(field); - field.id_attribute = u"field-id-attribute-2"; - field.name_attribute = u"field-name-attribute-2"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-2"); + field.set_name_attribute(u"field-name-attribute-2"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-descriptionm"; @@ -1592,9 +1592,9 @@ field.placeholder = u"field-placeholder"; form.fields.push_back(field); - field.id_attribute = u"field-id-attribute-3"; - field.name_attribute = u"field-name-attribute-3"; - field.set_name(field.name_attribute); + field.set_id_attribute(u"field-id-attribute-3"); + field.set_name_attribute(u"field-name-attribute-3"); + field.set_name(field.name_attribute()); field.set_label(u"field-label"); field.aria_label = u"field-aria-label"; field.aria_description = u"field-aria-descriptionm";
diff --git a/components/autofill/core/browser/form_forest_test_api.cc b/components/autofill/core/browser/form_forest_test_api.cc index 578a716..2b19739 100644 --- a/components/autofill/core/browser/form_forest_test_api.cc +++ b/components/autofill/core/browser/form_forest_test_api.cc
@@ -101,11 +101,11 @@ os << prefix << std::setfill(' ') << std::setw(2) << ++i << ". Field " << *field.renderer_id() << " at " << field.host_frame << " at " << field.origin.Serialize() << std::endl; - if (!field.id_attribute.empty()) { - os << prefix << " ID " << field.id_attribute << std::endl; + if (!field.id_attribute().empty()) { + os << prefix << " ID " << field.id_attribute() << std::endl; } - if (!field.name_attribute.empty()) { - os << prefix << " Name " << field.name_attribute << std::endl; + if (!field.name_attribute().empty()) { + os << prefix << " Name " << field.name_attribute() << std::endl; } if (!field.value().empty()) { os << prefix << " Value " << field.value() << std::endl;
diff --git a/components/autofill/core/browser/heuristic_classification_unittests.cc b/components/autofill/core/browser/heuristic_classification_unittests.cc index ae67f27..bef147c 100644 --- a/components/autofill/core/browser/heuristic_classification_unittests.cc +++ b/components/autofill/core/browser/heuristic_classification_unittests.cc
@@ -321,18 +321,18 @@ FormFieldData field; if (const std::string* id = field_dict.FindString("id_attr")) { - field.id_attribute = base::UTF8ToUTF16(*id); + field.set_id_attribute(base::UTF8ToUTF16(*id)); } if (const std::string* name = field_dict.FindString("name_attr")) { - field.name_attribute = base::UTF8ToUTF16(*name); + field.set_name_attribute(base::UTF8ToUTF16(*name)); } // `FormFieldData::name` is used for form signature calculation and a fallback // from a field's name to the field's id. field.set_name(std::u16string( - base::TrimWhitespace(field.name_attribute, base::TRIM_ALL))); + base::TrimWhitespace(field.name_attribute(), base::TRIM_ALL))); if (field.name().empty()) { field.set_name(std::u16string( - base::TrimWhitespace(field.id_attribute, base::TRIM_ALL))); + base::TrimWhitespace(field.id_attribute(), base::TRIM_ALL))); } if (const std::string* label = field_dict.FindString("label_attr")) {
diff --git a/components/autofill/core/common/field_data_manager_unittest.cc b/components/autofill/core/common/field_data_manager_unittest.cc index 699fefc..a22bb30 100644 --- a/components/autofill/core/common/field_data_manager_unittest.cc +++ b/components/autofill/core/common/field_data_manager_unittest.cc
@@ -18,14 +18,14 @@ protected: void SetUp() override { FormFieldData field1; - field1.id_attribute = u"name1"; + field1.set_id_attribute(u"name1"); field1.set_value(u"first"); field1.set_form_control_type(FormControlType::kInputText); field1.set_renderer_id(FieldRendererId(1)); control_elements_.push_back(field1); FormFieldData field2; - field2.id_attribute = u"name2"; + field2.set_id_attribute(u"name2"); field2.set_form_control_type(FormControlType::kInputPassword); field2.set_renderer_id(FieldRendererId(2)); control_elements_.push_back(field2);
diff --git a/components/autofill/core/common/form_data_fuzzed_producer.cc b/components/autofill/core/common/form_data_fuzzed_producer.cc index c8fa98a..8dc7abbb6 100644 --- a/components/autofill/core/common/form_data_fuzzed_producer.cc +++ b/components/autofill/core/common/form_data_fuzzed_producer.cc
@@ -67,8 +67,8 @@ provider.ConsumeRandomLengthString(); result.fields[i].set_label(ConsumeU16String(provider)); result.fields[i].set_name(ConsumeU16String(provider)); - result.fields[i].name_attribute = result.fields[i].name(); - result.fields[i].id_attribute = ConsumeU16String(provider); + result.fields[i].set_name_attribute(result.fields[i].name()); + result.fields[i].set_id_attribute(ConsumeU16String(provider)); result.fields[i].set_renderer_id( FieldRendererId(provider.ConsumeIntegralInRange(-32, 31)));
diff --git a/components/autofill/core/common/form_field_data.cc b/components/autofill/core/common/form_field_data.cc index a3129a5..5df60f9 100644 --- a/components/autofill/core/common/form_field_data.cc +++ b/components/autofill/core/common/form_field_data.cc
@@ -236,7 +236,7 @@ if (!iter->ReadString16(&id_attribute)) { return false; } - field_data->id_attribute = std::move(id_attribute); + field_data->set_id_attribute(std::move(id_attribute)); return true; } @@ -246,13 +246,13 @@ if (!iter->ReadString16(&name_attribute)) { return false; } - field_data->name_attribute = std::move(name_attribute); + field_data->set_name_attribute(std::move(name_attribute)); return true; } auto IdentityTuple(const FormFieldData& f) { return std::tuple_cat( - std::tie(f.label(), f.name(), f.name_attribute, f.id_attribute, + std::tie(f.label(), f.name(), f.name_attribute(), f.id_attribute(), f.form_control_type(), f.autocomplete_attribute, f.placeholder, f.max_length, f.css_classes, f.is_focusable, f.should_autocomplete, f.role, f.text_direction, f.options), @@ -499,8 +499,8 @@ pickle->WriteString16(field_data.placeholder); pickle->WriteString16(field_data.css_classes); pickle->WriteUInt32(field_data.properties_mask); - pickle->WriteString16(field_data.id_attribute); - pickle->WriteString16(field_data.name_attribute); + pickle->WriteString16(field_data.id_attribute()); + pickle->WriteString16(field_data.name_attribute()); } bool DeserializeFormFieldData(base::PickleIterator* iter, @@ -645,8 +645,8 @@ return os << "label='" << field.label() << "' " << "unique_Id=" << field.global_id() << " " << "origin='" << field.origin.Serialize() << "' " << "name='" << field.name() - << "' " << "id_attribute='" << field.id_attribute << "' " - << "name_attribute='" << field.name_attribute << "' " << "value='" + << "' " << "id_attribute='" << field.id_attribute() << "' " + << "name_attribute='" << field.name_attribute() << "' " << "value='" << field.value() << "' " << "control='" << field.form_control_type() << "' " << "autocomplete='" << field.autocomplete_attribute << "' " << "parsed_autocomplete='" @@ -681,8 +681,8 @@ "), host form renderer id: ", base::NumberToString(field.host_form_id.value())}); buffer << Tr{} << "Origin:" << field.origin.Serialize(); - buffer << Tr{} << "Name attribute:" << field.name_attribute; - buffer << Tr{} << "Id attribute:" << field.id_attribute; + buffer << Tr{} << "Name attribute:" << field.name_attribute(); + buffer << Tr{} << "Id attribute:" << field.id_attribute(); constexpr size_t kMaxLabelSize = 100; const std::u16string truncated_label = field.label().substr(0, std::min(field.label().length(), kMaxLabelSize));
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h index 789a0301..f069cd2 100644 --- a/components/autofill/core/common/form_field_data.h +++ b/components/autofill/core/common/form_field_data.h
@@ -274,8 +274,14 @@ const std::u16string& name() const { return name_; } void set_name(std::u16string name) { name_ = std::move(name); } - std::u16string id_attribute; - std::u16string name_attribute; + const std::u16string& id_attribute() const { return id_attribute_; } + void set_id_attribute(std::u16string id_attribute) { + id_attribute_ = std::move(id_attribute); + } + const std::u16string& name_attribute() const { return name_attribute_; } + void set_name_attribute(std::u16string name_attribute) { + name_attribute_ = std::move(name_attribute); + } const std::u16string& label() const { return label_; } void set_label(std::u16string label) { label_ = std::move(label); } @@ -431,6 +437,8 @@ private: std::u16string name_; + std::u16string id_attribute_; + std::u16string name_attribute_; std::u16string label_; std::u16string value_; FormControlType form_control_type_ = FormControlType::kInputText; @@ -525,8 +533,8 @@ EXPECT_EQ(expected.section, actual.section); \ EXPECT_EQ(expected.check_status, actual.check_status); \ EXPECT_EQ(expected.properties_mask, actual.properties_mask); \ - EXPECT_EQ(expected.id_attribute, actual.id_attribute); \ - EXPECT_EQ(expected.name_attribute, actual.name_attribute); \ + EXPECT_EQ(expected.id_attribute(), actual.id_attribute()); \ + EXPECT_EQ(expected.id_attribute(), actual.id_attribute()); \ } while (0) // Produces a <table> element with information about the form.
diff --git a/components/autofill/core/common/form_field_data_unittest.cc b/components/autofill/core/common/form_field_data_unittest.cc index 4532eac..3b20600 100644 --- a/components/autofill/core/common/form_field_data_unittest.cc +++ b/components/autofill/core/common/form_field_data_unittest.cc
@@ -48,11 +48,11 @@ } void FillVersion7Fields(FormFieldData* data) { - data->id_attribute = u"id"; + data->set_id_attribute(u"id"); } void FillVersion8Fields(FormFieldData* data) { - data->name_attribute = u"name"; + data->set_name_attribute(u"name"); } void WriteSection1(const FormFieldData& data, base::Pickle* pickle) { @@ -115,11 +115,11 @@ } void WriteVersion7Specific(const FormFieldData& data, base::Pickle* pickle) { - pickle->WriteString16(data.id_attribute); + pickle->WriteString16(data.id_attribute()); } void WriteVersion8Specific(const FormFieldData& data, base::Pickle* pickle) { - pickle->WriteString16(data.name_attribute); + pickle->WriteString16(data.name_attribute()); } void SerializeInVersion1Format(const FormFieldData& data,
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc index f58abbe..4c9e632 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.cc
@@ -186,14 +186,14 @@ if (!data.ReadIdAttribute(&id_attribute)) { return false; } - out->id_attribute = std::move(id_attribute); + out->set_id_attribute(std::move(id_attribute)); } { std::u16string name_attribute; if (!data.ReadNameAttribute(&name_attribute)) { return false; } - out->name_attribute = std::move(name_attribute); + out->set_name_attribute(std::move(name_attribute)); } { std::u16string value;
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h index 7c446dff..50abfbc 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -198,12 +198,12 @@ } static const std::u16string& id_attribute(const autofill::FormFieldData& r) { - return r.id_attribute; + return r.id_attribute(); } static const std::u16string& name_attribute( const autofill::FormFieldData& r) { - return r.name_attribute; + return r.name_attribute(); } static const std::u16string& value(const autofill::FormFieldData& r) {
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc index 31f74dfa..8d271a3 100644 --- a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc +++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -337,8 +337,8 @@ // Set other attributes to check if they are passed correctly. input.host_frame = test::MakeLocalFrameToken(); input.set_name(u"name"); - input.id_attribute = u"id"; - input.name_attribute = u"name"; + input.set_id_attribute(u"id"); + input.set_name_attribute(u"name"); input.set_value(u"value"); input.set_form_control_type(FormControlType::kInputText); input.autocomplete_attribute = "on"; @@ -381,8 +381,8 @@ // Set other attributes to check if they are passed correctly. input.host_frame = test::MakeLocalFrameToken(); input.set_renderer_id(FieldRendererId(1234)); - input.id_attribute = u"id"; - input.name_attribute = u"name"; + input.set_id_attribute(u"id"); + input.set_name_attribute(u"name"); input.autocomplete_attribute = "on"; input.parsed_autocomplete = std::nullopt; input.placeholder = u"placeholder";
diff --git a/components/autofill/ios/browser/autofill_agent_unittests.mm b/components/autofill/ios/browser/autofill_agent_unittests.mm index 43e3d993..014e7816 100644 --- a/components/autofill/ios/browser/autofill_agent_unittests.mm +++ b/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -155,32 +155,32 @@ field.set_form_control_type(autofill::FormControlType::kInputText); field.set_label(u"Card number"); field.set_name(u"number"); - field.name_attribute = field.name(); - field.id_attribute = u"number"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"number"); field.set_value(u"number_value"); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(2)); form.fields.push_back(field); field.set_label(u"Name on Card"); field.set_name(u"name"); - field.name_attribute = field.name(); - field.id_attribute = u"name"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"name"); field.set_value(u"name_value"); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(3)); form.fields.push_back(field); field.set_label(u"Expiry Month"); field.set_name(u"expiry_month"); - field.name_attribute = field.name(); - field.id_attribute = u"expiry_month"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"expiry_month"); field.set_value(u"01"); field.is_autofilled = false; field.set_renderer_id(FieldRendererId(4)); form.fields.push_back(field); field.set_label(u"Unknown field"); field.set_name(u"unknown"); - field.name_attribute = field.name(); - field.id_attribute = u"unknown"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"unknown"); field.set_value(u""); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(5)); @@ -206,8 +206,8 @@ field.set_form_control_type(autofill::FormControlType::kInputText); field.set_label(u"Card number"); field.set_name(u"number"); - field.name_attribute = field.name(); - field.id_attribute = u"number"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"number"); field.set_value(u"number_value"); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(2)); @@ -233,8 +233,8 @@ field.set_form_control_type(autofill::FormControlType::kInputText); field.set_label(u"Card number"); field.set_name(u"number"); - field.name_attribute = field.name(); - field.id_attribute = u"number"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"number"); field.set_value(u"number_value"); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(2)); @@ -264,8 +264,8 @@ field.set_form_control_type(autofill::FormControlType::kInputText); field.set_label(u"Card number"); field.set_name(u"number"); - field.name_attribute = field.name(); - field.id_attribute = u"number"; + field.set_name_attribute(field.name()); + field.set_id_attribute(u"number"); field.set_value(u"number_value"); field.is_autofilled = true; field.set_renderer_id(FieldRendererId(2));
diff --git a/components/autofill/ios/browser/autofill_util.mm b/components/autofill/ios/browser/autofill_util.mm index 7dbba88..7132732c 100644 --- a/components/autofill/ios/browser/autofill_util.mm +++ b/components/autofill/ios/browser/autofill_util.mm
@@ -296,10 +296,10 @@ // Optional fields. if (const std::string* name_attribute = field.FindString("name_attribute")) { - field_data->name_attribute = base::UTF8ToUTF16(*name_attribute); + field_data->set_name_attribute(base::UTF8ToUTF16(*name_attribute)); } if (const std::string* id_attribute = field.FindString("id_attribute")) { - field_data->id_attribute = base::UTF8ToUTF16(*id_attribute); + field_data->set_id_attribute(base::UTF8ToUTF16(*id_attribute)); } if (const std::string* label = field.FindString("label")) { field_data->set_label(base::UTF8ToUTF16(*label));
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp index 62062ea9..cbb37923 100644 --- a/components/autofill_payments_strings.grdp +++ b/components/autofill_payments_strings.grdp
@@ -1039,6 +1039,9 @@ <message name="IDS_AUTOFILL_CREDIT_CARD_DELETE_CONFIRMATION_TITLE" desc="Title for the confirmation dialog displayed when the user clicks on the delete button while editing card information." formatter_data="android_java"> Delete card </message> + <message name="IDS_AUTOFILL_IBAN_DELETE_CONFIRMATION_TITLE" desc="Title for the confirmation dialog displayed when the user clicks on the delete button while editing the IBAN information." formatter_data="android_java"> + Delete IBAN + </message> <message name="IDS_AUTOFILL_PAYMENT_METHOD_DELETE_CONFIRMATION_DESCRIPTION" desc="Description for the confirmation dialog displayed when the user clicks on the delete button while editing payment method information." formatter_data="android_java"> This payment method will be deleted from this device </message>
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_IBAN_DELETE_CONFIRMATION_TITLE.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_IBAN_DELETE_CONFIRMATION_TITLE.png.sha1 new file mode 100644 index 0000000..21390ec --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_IBAN_DELETE_CONFIRMATION_TITLE.png.sha1
@@ -0,0 +1 @@ +451008dd53bb83fcac9a20e0036212ec32f3f4aa \ No newline at end of file
diff --git a/components/cast_streaming/browser/public/receiver_config.h b/components/cast_streaming/browser/public/receiver_config.h index 400e03c..514b1a7e 100644 --- a/components/cast_streaming/browser/public/receiver_config.h +++ b/components/cast_streaming/browser/public/receiver_config.h
@@ -6,6 +6,7 @@ #define COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_RECEIVER_CONFIG_H_ #include <optional> +#include <vector> #include "base/time/time.h" #include "media/base/audio_codecs.h"
diff --git a/components/component_updater/installer_policies/tpcd_metadata_component_installer_policy_unittest.cc b/components/component_updater/installer_policies/tpcd_metadata_component_installer_policy_unittest.cc index e41abeb..4774c43 100644 --- a/components/component_updater/installer_policies/tpcd_metadata_component_installer_policy_unittest.cc +++ b/components/component_updater/installer_policies/tpcd_metadata_component_installer_policy_unittest.cc
@@ -270,7 +270,7 @@ tpcd::metadata::Metadata metadata; tpcd::metadata::helpers::AddEntryToMetadata( metadata, primary_pattern_spec, secondary_pattern_spec, - tpcd::metadata::Parser::kSourceTest, std::nullopt, + tpcd::metadata::Parser::kSourceCriticalSector, std::nullopt, tpcd::metadata::Parser::kMaxDtrp); ASSERT_EQ(metadata.metadata_entries_size(), 1); @@ -294,7 +294,8 @@ tpcd::metadata::Metadata metadata; tpcd::metadata::helpers::AddEntryToMetadata(metadata, primary_pattern_spec, - secondary_pattern_spec); + secondary_pattern_spec, + Parser::kSourceCriticalSector); ASSERT_EQ(metadata.metadata_entries_size(), 1); ExecFakeComponentInstallation(metadata.SerializeAsString()); @@ -330,7 +331,8 @@ tpcd::metadata::Metadata metadata; tpcd::metadata::helpers::AddEntryToMetadata(metadata, primary_pattern_spec, - secondary_pattern_spec); + secondary_pattern_spec, + Parser::kSourceCriticalSector); ASSERT_EQ(metadata.metadata_entries_size(), 1); ExecFakeComponentInstallation(metadata.SerializeAsString());
diff --git a/components/cross_device/nearby/BUILD.gn b/components/cross_device/nearby/BUILD.gn index 5d190701..d12c32a 100644 --- a/components/cross_device/nearby/BUILD.gn +++ b/components/cross_device/nearby/BUILD.gn
@@ -2,6 +2,18 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +source_set("platform") { + sources = [ + "crypto.cc", + "system_clock.cc", + ] + deps = [ + "//base", + "//crypto", + "//third_party/nearby:platform_api_types", + ] +} + source_set("nearby") { sources = [ "nearby_features.cc", @@ -9,3 +21,15 @@ ] deps = [ "//base" ] } + +source_set("unit_tests") { + testonly = true + sources = [ "crypto_unittest.cc" ] + + deps = [ + ":platform", + "//base/test:test_support", + "//testing/gtest", + "//third_party/nearby:platform_api_types", + ] +}
diff --git a/components/cross_device/nearby/DEPS b/components/cross_device/nearby/DEPS new file mode 100644 index 0000000..322bf74a --- /dev/null +++ b/components/cross_device/nearby/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + '+crypto/sha2.h', + '+third_party/abseil-cpp/absl/time/time.h', + '+third_party/nearby/src/internal/platform/implementation/crypto.h', + '+third_party/nearby/src/internal/platform/implementation/system_clock.h', +]
diff --git a/chrome/services/sharing/nearby/platform/crypto.cc b/components/cross_device/nearby/crypto.cc similarity index 92% rename from chrome/services/sharing/nearby/platform/crypto.cc rename to components/cross_device/nearby/crypto.cc index a9530c9..bdf129f9 100644 --- a/chrome/services/sharing/nearby/platform/crypto.cc +++ b/components/cross_device/nearby/crypto.cc
@@ -8,7 +8,6 @@ #include "base/hash/md5.h" #include "base/memory/ptr_util.h" #include "crypto/sha2.h" -#include "third_party/abseil-cpp/absl/strings/string_view.h" #include <vector>
diff --git a/chrome/services/sharing/nearby/platform/crypto_unittest.cc b/components/cross_device/nearby/crypto_unittest.cc similarity index 100% rename from chrome/services/sharing/nearby/platform/crypto_unittest.cc rename to components/cross_device/nearby/crypto_unittest.cc
diff --git a/chrome/services/sharing/nearby/platform/system_clock.cc b/components/cross_device/nearby/system_clock.cc similarity index 100% rename from chrome/services/sharing/nearby/platform/system_clock.cc rename to components/cross_device/nearby/system_clock.cc
diff --git a/components/dbus/properties/types.cc b/components/dbus/properties/types.cc index 888ebf8..d9f4aff6 100644 --- a/components/dbus/properties/types.cc +++ b/components/dbus/properties/types.cc
@@ -146,8 +146,7 @@ bool DbusByteArray::IsEqual(const DbusType& other_type) const { const DbusByteArray* other = static_cast<const DbusByteArray*>(&other_type); - return value_->size() == other->value_->size() && - !memcmp(value_->front(), other->value_->front(), value_->size()); + return value_->Equals(other->value_); } void DbusByteArray::Write(dbus::MessageWriter* writer) const {
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc index 78cd5dd..5028c22 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.cc
@@ -131,6 +131,8 @@ .SetResult(static_cast<uint8_t>(result)) .SetLatencyInMillis(GetPixCodeDetectionLatencyInMillis()) .SetAttempts(pix_code_detection_attempt_count_) + .SetDetectionTriggeredOnDomContentLoaded( + base::FeatureList::IsEnabled(kEnablePixDetectionOnDomContentLoaded)) .Record(ukm::UkmRecorder::Get()); if (result == mojom::PixCodeDetectionResult::kValidPixCodeFound &&
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager.h b/components/facilitated_payments/core/browser/facilitated_payments_manager.h index ec9d366..be5718e 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager.h +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager.h
@@ -119,6 +119,11 @@ FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, RetrievesClientTokenIfPixPaymentPromptAccepted); FRIEND_TEST_ALL_PREFIXES( + FacilitatedPaymentsManagerTest, + TriggerPixDetectionOnDomContentLoadedExpDisabled_Ukm); + FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerTest, + TriggerPixDetectionOnDomContentLoadedExpEnabled_Ukm); + FRIEND_TEST_ALL_PREFIXES( FacilitatedPaymentsManagerWithPixPaymentsDisabledTest, ValidPixCodeDetectionResultDoesNotTriggerApiClient); FRIEND_TEST_ALL_PREFIXES(FacilitatedPaymentsManagerWithPixPaymentsEnabledTest,
diff --git a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc index 92214b4..7e98bfbe 100644 --- a/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc +++ b/components/facilitated_payments/core/browser/facilitated_payments_manager_unittest.cc
@@ -229,6 +229,7 @@ } protected: + base::test::ScopedFeatureList features_; optimization_guide::OptimizationGuideDecision allowlist_result_; mojom::PixCodeDetectionResult pix_code_detection_result_; std::unique_ptr<MockOptimizationGuideDecider> optimization_guide_decider_; @@ -818,6 +819,42 @@ /*selected_instrument_id=*/-1); } +TEST_F(FacilitatedPaymentsManagerTest, + TriggerPixDetectionOnDomContentLoadedExpDisabled_Ukm) { + features_.InitAndDisableFeature(kEnablePixDetectionOnDomContentLoaded); + + manager_->ProcessPixCodeDetectionResult( + mojom::PixCodeDetectionResult::kValidPixCodeFound, std::string()); + + auto ukm_entries = ukm_recorder_.GetEntries( + ukm::builders::FacilitatedPayments_PixCodeDetectionResult::kEntryName, + {ukm::builders::FacilitatedPayments_PixCodeDetectionResult:: + kDetectionTriggeredOnDomContentLoadedName}); + + // Verify that the UKM metrics are logged. + EXPECT_EQ(ukm_entries.size(), 1UL); + EXPECT_EQ(ukm_entries[0].metrics.at("DetectionTriggeredOnDomContentLoaded"), + false); +} + +TEST_F(FacilitatedPaymentsManagerTest, + TriggerPixDetectionOnDomContentLoadedExpEnabled_Ukm) { + features_.InitAndEnableFeature(kEnablePixDetectionOnDomContentLoaded); + + manager_->ProcessPixCodeDetectionResult( + mojom::PixCodeDetectionResult::kValidPixCodeFound, std::string()); + + auto ukm_entries = ukm_recorder_.GetEntries( + ukm::builders::FacilitatedPayments_PixCodeDetectionResult::kEntryName, + {ukm::builders::FacilitatedPayments_PixCodeDetectionResult:: + kDetectionTriggeredOnDomContentLoadedName}); + + // Verify that the UKM metrics are logged. + EXPECT_EQ(ukm_entries.size(), 1UL); + EXPECT_EQ(ukm_entries[0].metrics.at("DetectionTriggeredOnDomContentLoaded"), + true); +} + // A test fixture for the facilitated payment manager with the // kEnablePixPayments feature flag disabled. class FacilitatedPaymentsManagerWithPixPaymentsDisabledTest @@ -828,9 +865,6 @@ } ~FacilitatedPaymentsManagerWithPixPaymentsDisabledTest() override = default; - - private: - base::test::ScopedFeatureList features_; }; // If the kEnablePixPayments flag is disabled when a valid PIX code is detected, @@ -853,9 +887,6 @@ } ~FacilitatedPaymentsManagerWithPixPaymentsEnabledTest() override = default; - - private: - base::test::ScopedFeatureList features_; }; // If the kEnablePixPayments flag is enabled when a valid PIX code is detected,
diff --git a/components/favicon/core/favicon_backend.cc b/components/favicon/core/favicon_backend.cc index b09db7b..53a940a 100644 --- a/components/favicon/core/favicon_backend.cc +++ b/components/favicon/core/favicon_backend.cc
@@ -565,7 +565,7 @@ for (size_t i = 0; i < bitmaps.size(); ++i) { scoped_refptr<base::RefCountedBytes> bitmap_data(new base::RefCountedBytes); if (!gfx::PNGCodec::EncodeBGRASkBitmap(bitmaps[i], false, - &bitmap_data->data())) { + &bitmap_data->as_vector())) { continue; } to_add.push_back(std::make_pair(
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc index b4f0eb59..2bc6dcf 100644 --- a/components/favicon/core/favicon_handler_unittest.cc +++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -100,7 +100,7 @@ int edge_size = gfx::kFaviconSize, SkColor color = SK_ColorRED) { scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); - data->data() = FillBitmapWithEdgeSize(edge_size, color); + data->as_vector() = FillBitmapWithEdgeSize(edge_size, color); FaviconRawBitmapResult bitmap_result; bitmap_result.expired = expired; bitmap_result.bitmap_data = data;
diff --git a/components/favicon/core/favicon_util.cc b/components/favicon/core/favicon_util.cc index a4ee3d5..618e197 100644 --- a/components/favicon/core/favicon_util.cc +++ b/components/favicon/core/favicon_util.cc
@@ -19,7 +19,7 @@ favicon_base::FaviconImageResult result; if (bitmap_result.is_valid()) { result.image = gfx::Image::CreateFrom1xPNGBytes( - bitmap_result.bitmap_data->front(), bitmap_result.bitmap_data->size()); + bitmap_result.bitmap_data->data(), bitmap_result.bitmap_data->size()); result.icon_url = bitmap_result.icon_url; std::move(callback).Run(result); return;
diff --git a/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc b/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc index 5d5ad10..583026c 100644 --- a/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc +++ b/components/favicon/core/history_ui_favicon_request_handler_impl_unittest.cc
@@ -39,7 +39,7 @@ scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); gfx::PNGCodec::EncodeBGRASkBitmap( gfx::test::CreateBitmap(desired_size_in_pixel, SK_ColorRED), false, - &data->data()); + &data->as_vector()); favicon_base::FaviconRawBitmapResult result; result.bitmap_data = data; result.icon_url = icon_url;
diff --git a/components/favicon/core/large_icon_service_impl_unittest.cc b/components/favicon/core/large_icon_service_impl_unittest.cc index b7264e7..633165a 100644 --- a/components/favicon/core/large_icon_service_impl_unittest.cc +++ b/components/favicon/core/large_icon_service_impl_unittest.cc
@@ -76,7 +76,7 @@ // Create bitmap and fill with |color|. scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); gfx::PNGCodec::EncodeBGRASkBitmap(gfx::test::CreateBitmap(w, h, color), false, - &data->data()); + &data->as_vector()); result.bitmap_data = data; result.pixel_size = gfx::Size(w, h);
diff --git a/components/favicon/core/large_icon_worker.cc b/components/favicon/core/large_icon_worker.cc index 221d23c..2ae56e0 100644 --- a/components/favicon/core/large_icon_worker.cc +++ b/components/favicon/core/large_icon_worker.cc
@@ -36,7 +36,7 @@ const favicon_base::FaviconRawBitmapResult& db_result, int desired_size) { gfx::Image image = gfx::Image::CreateFrom1xPNGBytes( - db_result.bitmap_data->front(), db_result.bitmap_data->size()); + db_result.bitmap_data->data(), db_result.bitmap_data->size()); if (desired_size == 0 || db_result.pixel_size.width() == desired_size) { return image;
diff --git a/components/favicon_base/favicon_util.cc b/components/favicon_base/favicon_util.cc index 56ab7b77..cdbe236d 100644 --- a/components/favicon_base/favicon_util.cc +++ b/components/favicon_base/favicon_util.cc
@@ -204,9 +204,8 @@ continue; SkBitmap bitmap; - if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), - png_data[i].bitmap_data->size(), - &bitmap)) { + if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->data(), + png_data[i].bitmap_data->size(), &bitmap)) { bitmaps.push_back(bitmap); } } @@ -233,9 +232,8 @@ scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes()); if (gfx::PNGCodec::EncodeBGRASkBitmap( resized_image_skia_reps[i].GetBitmap(), false, - &png_bytes->data())) { - png_reps.push_back( - gfx::ImagePNGRep(png_bytes, resized_image_skia_reps[i].scale())); + &png_bytes->as_vector())) { + png_reps.emplace_back(png_bytes, resized_image_skia_reps[i].scale()); } }
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java index 9ffd8ee..3bc939d 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -34,7 +34,6 @@ FeatureConstants.CHROME_HOME_PULL_TO_REFRESH_FEATURE, FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_QUIET_VARIANT, FeatureConstants.CONTEXTUAL_PAGE_ACTIONS_ACTION_CHIP, - FeatureConstants.COOKIE_CONTROLS_3PCD_FEATURE, FeatureConstants.COOKIE_CONTROLS_FEATURE, FeatureConstants.DATA_SAVER_PREVIEW_FEATURE, FeatureConstants.DATA_SAVER_DETAIL_FEATURE, @@ -124,7 +123,6 @@ String CCT_MINIMIZED_FEATURE = "IPH_CCTMinimized"; String CONTEXTUAL_PAGE_ACTIONS_QUIET_VARIANT = "IPH_ContextualPageActions_QuietVariant"; String CONTEXTUAL_PAGE_ACTIONS_ACTION_CHIP = "IPH_ContextualPageActions_ActionChip"; - String COOKIE_CONTROLS_3PCD_FEATURE = "IPH_3pcdUserBypass"; String COOKIE_CONTROLS_FEATURE = "IPH_CookieControls"; String DOWNLOAD_PAGE_FEATURE = "IPH_DownloadPage"; String DOWNLOAD_PAGE_SCREENSHOT_FEATURE = "IPH_DownloadPageScreenshot";
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc index c882d19..966f516 100644 --- a/components/feature_engagement/public/feature_configurations.cc +++ b/components/feature_engagement/public/feature_configurations.cc
@@ -1549,25 +1549,6 @@ return config; } - if (kIPH3pcdUserBypassFeature.name == feature->name) { - std::optional<FeatureConfig> config = FeatureConfig(); - config->valid = true; - config->availability = Comparator(ANY, 0); - config->session_rate = Comparator(ANY, 0); - config->session_rate_impact.type = SessionRateImpact::Type::NONE; - // Show promo only once and only if user hasn't interacted with - // the cookie controls bubble in the last year. - config->trigger = - EventConfig("iph_3pcd_user_bypass_triggered", Comparator(EQUAL, 0), - feature_engagement::kMaxStoragePeriod, - feature_engagement::kMaxStoragePeriod); -#if !BUILDFLAG(IS_ANDROID) - config->used = - EventConfig(feature_engagement::events::kCookieControlsBubbleShown, - Comparator(ANY, 0), 360, 360); -#endif // !BUILDFLAG(IS_ANDROID) - return config; - } #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc index 34648e4..547abbc0 100644 --- a/components/feature_engagement/public/feature_constants.cc +++ b/components/feature_engagement/public/feature_constants.cc
@@ -600,9 +600,6 @@ BASE_FEATURE(kIPHCookieControlsFeature, "IPH_CookieControls", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kIPH3pcdUserBypassFeature, - "IPH_3pcdUserBypass", - base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index e23993e..ff91542 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -251,7 +251,6 @@ BASE_DECLARE_FEATURE(kIPHAutofillVirtualCardCVCSuggestionFeature); BASE_DECLARE_FEATURE(kIPHAutofillVirtualCardSuggestionFeature); BASE_DECLARE_FEATURE(kIPHCookieControlsFeature); -BASE_DECLARE_FEATURE(kIPH3pcdUserBypassFeature); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc index 0a7117b7..d9caeff 100644 --- a/components/feature_engagement/public/feature_list.cc +++ b/components/feature_engagement/public/feature_list.cc
@@ -210,7 +210,6 @@ &kIPHAutofillVirtualCardCVCSuggestionFeature, &kIPHAutofillVirtualCardSuggestionFeature, &kIPHCookieControlsFeature, - &kIPH3pcdUserBypassFeature, #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index b69108a2..50b9d4c 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -373,7 +373,6 @@ DEFINE_VARIATION_PARAM(kIPHAutofillVirtualCardSuggestionFeature, "IPH_AutofillVirtualCardSuggestion"); DEFINE_VARIATION_PARAM(kIPHCookieControlsFeature, "IPH_CookieControls"); -DEFINE_VARIATION_PARAM(kIPH3pcdUserBypassFeature, "IPH_3pcdUserBypass"); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_FUCHSIA) @@ -660,7 +659,6 @@ VARIATION_ENTRY(kIPHAutofillVirtualCardCVCSuggestionFeature), VARIATION_ENTRY(kIPHAutofillVirtualCardSuggestionFeature), VARIATION_ENTRY(kIPHCookieControlsFeature), - VARIATION_ENTRY(kIPH3pcdUserBypassFeature), #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || // BUILDFLAG(IS_FUCHSIA)
diff --git a/components/feedback/content/content_tracing_manager_browsertest.cc b/components/feedback/content/content_tracing_manager_browsertest.cc index 95014451..f7d4abb 100644 --- a/components/feedback/content/content_tracing_manager_browsertest.cc +++ b/components/feedback/content/content_tracing_manager_browsertest.cc
@@ -106,7 +106,7 @@ EXPECT_EQ(trace_id, 1); tracing_manager->GetTraceData(trace_id, future.GetCallback()); // The actual trace data varies. - EXPECT_TRUE(future.Get()->data().size() > 0); + EXPECT_TRUE(future.Get()->size() > 0u); } // Test that FeedbackData.CompressSystemInfo will not gather trace data when the
diff --git a/components/feedback/feedback_data.cc b/components/feedback/feedback_data.cc index 08f7fe6..4975ebf6 100644 --- a/components/feedback/feedback_data.cc +++ b/components/feedback/feedback_data.cc
@@ -131,7 +131,9 @@ if (tracing_manager_) tracing_manager_->DiscardTraceData(trace_id); - AddFile(kTraceFilename, std::move(trace_data->data())); + std::string s; + std::swap(s, trace_data->as_string()); + AddFile(kTraceFilename, std::move(s)); set_category_tag(kPerformanceCategoryTag); --pending_op_count_;
diff --git a/components/fingerprinting_protection_filter/browser/BUILD.gn b/components/fingerprinting_protection_filter/browser/BUILD.gn index 10f54fb..dc3abfb62 100644 --- a/components/fingerprinting_protection_filter/browser/BUILD.gn +++ b/components/fingerprinting_protection_filter/browser/BUILD.gn
@@ -2,18 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("browser") { +source_set("browser") { sources = [ "fingerprinting_protection_filter_constants.cc", "fingerprinting_protection_filter_constants.h", - "fingerprinting_protection_filter_features.cc", - "fingerprinting_protection_filter_features.h", "fingerprinting_protection_page_activation_throttle.cc", "fingerprinting_protection_page_activation_throttle.h", "fingerprinting_protection_web_contents_helper.cc", "fingerprinting_protection_web_contents_helper.h", ] public_deps = [ + ":features", "//base", "//components/subresource_filter/content/shared/browser", "//components/subresource_filter/core/browser", @@ -24,3 +23,13 @@ "//components/subresource_filter/core/mojom", ] } + +component("features") { + output_name = "fingerprinting_protection_filter_features" + defines = [ "IS_FINGERPRINTING_PROTECTION_FILTER_FEATURES_IMPL" ] + sources = [ + "fingerprinting_protection_filter_features.cc", + "fingerprinting_protection_filter_features.h", + ] + public_deps = [ "//base" ] +}
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.cc b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.cc index a6ca6ae2..2e5259f 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.cc +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.cc
@@ -6,6 +6,9 @@ namespace fingerprinting_protection_filter::features { +// When enabled, loads the Fingerprinting Protection component and evaluates +// resource requests on certain pages against the Fingerprinting Protection +// blocklist, possibly blocks via a subresource filter. BASE_FEATURE(kEnableFingerprintingProtectionFilter, "EnableFingerprintingProtectionFilter", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h index d7364f0..c9037ccd 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_filter_features.h
@@ -5,11 +5,13 @@ #ifndef COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_BROWSER_FINGERPRINTING_PROTECTION_FILTER_FEATURES_H_ #define COMPONENTS_FINGERPRINTING_PROTECTION_FILTER_BROWSER_FINGERPRINTING_PROTECTION_FILTER_FEATURES_H_ +#include "base/component_export.h" #include "base/feature_list.h" namespace fingerprinting_protection_filter::features { // The primary toggle to enable/disable the Fingerprinting Protection Filter. +COMPONENT_EXPORT(FINGERPRINTING_PROTECTION_FILTER_FEATURES) BASE_DECLARE_FEATURE(kEnableFingerprintingProtectionFilter); } // namespace fingerprinting_protection_filter::features
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc index 1709564..1eb9705 100644 --- a/components/history_clusters/core/config.cc +++ b/components/history_clusters/core/config.cc
@@ -312,9 +312,6 @@ base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kShouldShowAllClustersOnProminentUiSurfaces); - include_synced_visits = - base::FeatureList::IsEnabled(internal::kJourneysIncludeSyncedVisits); - persist_caches_to_prefs = base::FeatureList::IsEnabled(internal::kJourneysPersistCachesToPrefs); }
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h index 96ec1931..56f4de3 100644 --- a/components/history_clusters/core/config.h +++ b/components/history_clusters/core/config.h
@@ -300,9 +300,6 @@ bool should_show_all_clusters_unconditionally_on_prominent_ui_surfaces = false; - // Whether to include synced visits in clusters. - bool include_synced_visits = false; - // Whether keyword caches should be written to and read from prefs. bool persist_caches_to_prefs = true;
diff --git a/components/history_clusters/core/features.cc b/components/history_clusters/core/features.cc index b15074c..8aa12348 100644 --- a/components/history_clusters/core/features.cc +++ b/components/history_clusters/core/features.cc
@@ -72,12 +72,6 @@ "HistoryClustersVisitDeduping", base::FEATURE_DISABLED_BY_DEFAULT); -// TODO(manukh): Enabled by default in m122; clean up feature code in 2/21/24 -// when m122 reaches stable. -BASE_FEATURE(kJourneysIncludeSyncedVisits, - "JourneysIncludeSyncedVisits", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kJourneysPersistCachesToPrefs, "JourneysPersistCachesToPrefs", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/history_clusters/core/features.h b/components/history_clusters/core/features.h index ee16c95..7df804b 100644 --- a/components/history_clusters/core/features.h +++ b/components/history_clusters/core/features.h
@@ -63,9 +63,6 @@ // Enables experimentation for how to dedupe visits in clusters. BASE_DECLARE_FEATURE(kHistoryClustersVisitDeduping); -// Enables visits from other synced devices to be included in clusters. -BASE_DECLARE_FEATURE(kJourneysIncludeSyncedVisits); - // Persist keyword caches via pref service. BASE_DECLARE_FEATURE(kJourneysPersistCachesToPrefs);
diff --git a/components/history_clusters/core/history_clusters_db_tasks.cc b/components/history_clusters/core/history_clusters_db_tasks.cc index 4bfce5f..e73b545 100644 --- a/components/history_clusters/core/history_clusters_db_tasks.cc +++ b/components/history_clusters/core/history_clusters_db_tasks.cc
@@ -170,10 +170,7 @@ continue; } - if ((visit.source != history::SOURCE_SYNCED) || - GetConfig().include_synced_visits) { - annotated_visits_.push_back(std::move(visit)); - } + annotated_visits_.push_back(std::move(visit)); } return limited_by_max_count;
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc index c9242faf..e2ced0b 100644 --- a/components/history_clusters/core/history_clusters_service.cc +++ b/components/history_clusters/core/history_clusters_service.cc
@@ -479,12 +479,6 @@ // simple first-pass technique to avoid overtriggering the omnibox action. continue; } - if (!GetConfig().include_synced_visits && - !cluster.originator_cache_guid.empty()) { - // Skip over remote clusters if remote visits do not intend to get - // incorporated. - continue; - } // Lowercase the keywords for case insensitive matching while adding to the // accumulator. // Keep the keyword data with the highest score if found in multiple
diff --git a/components/history_clusters/core/history_clusters_service.h b/components/history_clusters/core/history_clusters_service.h index c8dd88f..92333ce 100644 --- a/components/history_clusters/core/history_clusters_service.h +++ b/components/history_clusters/core/history_clusters_service.h
@@ -175,7 +175,7 @@ private: friend class HistoryClustersServiceTestApi; - friend class HistoryClustersServiceTestBase; + friend class HistoryClustersServiceTest; // Invokes `UpdateClusters()` after a short delay, then again periodically. // E.g., might invoke `UpdateClusters()` initially 5 minutes after startup,
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc index 4bd10623..20ac5fb 100644 --- a/components/history_clusters/core/history_clusters_service_unittest.cc +++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -132,9 +132,9 @@ std::vector<history::Cluster> last_clustered_clusters_; }; -class HistoryClustersServiceTestBase : public testing::Test { +class HistoryClustersServiceTest : public testing::Test { public: - HistoryClustersServiceTestBase() + HistoryClustersServiceTest() : task_environment_( base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME) { Config config; @@ -164,10 +164,9 @@ history_service_.reset(); } - HistoryClustersServiceTestBase(const HistoryClustersServiceTestBase&) = + HistoryClustersServiceTest(const HistoryClustersServiceTest&) = delete; + HistoryClustersServiceTest& operator=(const HistoryClustersServiceTest&) = delete; - HistoryClustersServiceTestBase& operator=( - const HistoryClustersServiceTestBase&) = delete; void ResetHistoryClustersServiceWithLocale(const std::string& locale) { history_clusters_service_ = std::make_unique<HistoryClustersService>( @@ -287,14 +286,14 @@ } // Verifies that the hardcoded visits were passed to the clustering backend. - void AwaitAndVerifyTestClusteringBackendRequest(bool expect_synced_visits) { + void AwaitAndVerifyTestClusteringBackendRequest() { test_clustering_backend_->WaitForGetClustersCall(); std::vector<history::AnnotatedVisit> visits = test_clustering_backend_->LastClusteredVisits(); // Visits 2, 3, and 5 are 1-day-old; visit 3 is a synced visit. - ASSERT_EQ(visits.size(), expect_synced_visits ? 3u : 2u); + ASSERT_EQ(visits.size(), 3u); auto& visit = visits[0]; EXPECT_EQ(visit.visit_row.visit_id, 5); @@ -305,16 +304,14 @@ EXPECT_EQ(visit.context_annotations.page_end_reason, 5); visit = visits[1]; - if (expect_synced_visits) { - EXPECT_EQ(visit.visit_row.visit_id, 3); - EXPECT_EQ(visit.visit_row.visit_time, - GetHardcodedTestVisits()[2].visit_row.visit_time); - EXPECT_EQ(visit.visit_row.visit_duration, base::Seconds(20)); - EXPECT_EQ(visit.url_row.url(), "https://synched-visit.com/"); - EXPECT_EQ(visit.context_annotations.page_end_reason, 5); + EXPECT_EQ(visit.visit_row.visit_id, 3); + EXPECT_EQ(visit.visit_row.visit_time, + GetHardcodedTestVisits()[2].visit_row.visit_time); + EXPECT_EQ(visit.visit_row.visit_duration, base::Seconds(20)); + EXPECT_EQ(visit.url_row.url(), "https://synched-visit.com/"); + EXPECT_EQ(visit.context_annotations.page_end_reason, 5); - visit = visits[2]; - } + visit = visits[2]; EXPECT_EQ(visit.visit_row.visit_id, 2); EXPECT_EQ(visit.visit_row.visit_time, GetHardcodedTestVisits()[1].visit_row.visit_time); @@ -336,7 +333,8 @@ std::vector<history::Cluster> clusters; base::RunLoop loop; QueryClustersFilterParams filter_params; - filter_params.include_synced_visits = GetConfig().include_synced_visits; + // Including synced visits launched in early 2024. + filter_params.include_synced_visits = true; const auto task = history_clusters_service_->QueryClusters( ClusteringRequestSource::kJourneysPage, filter_params, /*begin_time=*/base::Time(), continuation_params, /*recluster=*/false, @@ -440,28 +438,7 @@ int64_t next_navigation_id_ = 0; }; -class HistoryClustersServiceTest : public HistoryClustersServiceTestBase, - public ::testing::WithParamInterface<bool> { - public: - HistoryClustersServiceTest() { - scoped_feature_list_.InitAndEnableFeature(internal::kJourneys); - Config config; - // TODO(b/276488340): Update this test when non context clusterer code gets - // cleaned up. - config.use_navigation_context_clusters = false; - config.include_synced_visits = ExpectSyncedVisits(); - SetConfigForTesting(config); - } - - // Whether synced visits are expected to be sent to the clustering backend. - bool ExpectSyncedVisits() const { return GetParam(); } -}; - -INSTANTIATE_TEST_SUITE_P(IncludeSyncedVisits, - HistoryClustersServiceTest, - ::testing::Bool()); - -TEST_P(HistoryClustersServiceTest, EligibleAndEnabledHistogramRecorded) { +TEST_F(HistoryClustersServiceTest, EligibleAndEnabledHistogramRecorded) { { base::HistogramTester histogram_tester; SetJourneysVisible(true); @@ -487,7 +464,7 @@ } } -TEST_P(HistoryClustersServiceTest, HardCapOnVisitsFetchedFromHistory) { +TEST_F(HistoryClustersServiceTest, HardCapOnVisitsFetchedFromHistory) { Config config; config.is_journeys_enabled_no_locale_check = true; config.max_visits_to_cluster = 20; @@ -540,7 +517,7 @@ EXPECT_EQ(test_clustering_backend_->LastClusteredVisits().size(), 20U); } -TEST_P(HistoryClustersServiceTest, QueryClusters_IncompleteAndPersistedVisits) { +TEST_F(HistoryClustersServiceTest, QueryClusters_IncompleteAndPersistedVisits) { // Create 5 persisted visits with visit times 2, 1, 1, 60, and 1 days ago. AddHardcodedTestDataToHistoryService(); @@ -563,11 +540,7 @@ { const auto [clusters, visits] = NextQueryClusters(continuation_params); EXPECT_THAT(GetClusterIds(clusters), testing::ElementsAre()); - if (ExpectSyncedVisits()) { - EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 3, 2, 6)); - } else { - EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 2, 6)); - } + EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 3, 2, 6)); EXPECT_TRUE(continuation_params.is_continuation); EXPECT_FALSE(continuation_params.is_partial_day); } @@ -597,7 +570,7 @@ } } -TEST_P(HistoryClustersServiceTest, +TEST_F(HistoryClustersServiceTest, QueryClusters_PersistedClusters_NoMixedDays) { // Test the case where there are persisted clusters but none on a day also // containing unclustered visits. @@ -664,7 +637,7 @@ } } -TEST_P(HistoryClustersServiceTest, +TEST_F(HistoryClustersServiceTest, QueryClusters_PersistedClusters_UseNavigationContextClusters) { // Test the case where there are persisted clusters but no unclustered visits. @@ -693,7 +666,6 @@ // Update config so that the new context clusters are used. Config new_config; new_config.use_navigation_context_clusters = true; - new_config.include_synced_visits = ExpectSyncedVisits(); SetConfigForTesting(new_config); QueryClustersContinuationParams continuation_params = {}; @@ -701,18 +673,13 @@ { const auto [clusters, visits] = NextQueryClusters(continuation_params, true); - std::vector<int64_t> expected_cluster_ids = {1, 2, 3}; - if (ExpectSyncedVisits()) { - expected_cluster_ids.push_back(4); - } + std::vector<int64_t> expected_cluster_ids = {1, 2, 3, 4}; ASSERT_THAT(GetClusterIds(clusters), testing::ElementsAreArray(expected_cluster_ids)); EXPECT_THAT(GetVisitIds(clusters[0].visits), testing::ElementsAre(1)); EXPECT_THAT(GetVisitIds(clusters[1].visits), testing::ElementsAre(2)); EXPECT_THAT(GetVisitIds(clusters[2].visits), testing::ElementsAre(3)); - if (ExpectSyncedVisits()) { - EXPECT_THAT(GetVisitIds(clusters[3].visits), testing::ElementsAre(4)); - } + EXPECT_THAT(GetVisitIds(clusters[3].visits), testing::ElementsAre(4)); EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre()); EXPECT_TRUE(continuation_params.exhausted_unclustered_visits); EXPECT_FALSE(continuation_params.exhausted_all_visits); @@ -728,7 +695,7 @@ } } -TEST_P(HistoryClustersServiceTest, QueryClusters_PersistedClusters_Today) { +TEST_F(HistoryClustersServiceTest, QueryClusters_PersistedClusters_Today) { // Test the case where there is a persisted cluster today. The task rewinds // the query bounds when it reaches a clustered visit, and this should be done // correctly even if it's at the edge. @@ -774,7 +741,7 @@ } } -TEST_P(HistoryClustersServiceTest, QueryClusters_PersistedClusters_MixedDay) { +TEST_F(HistoryClustersServiceTest, QueryClusters_PersistedClusters_MixedDay) { // Test the case where there are persisted clusters on a day also containing // unclustered visits. @@ -838,7 +805,7 @@ } } -TEST_P(HistoryClustersServiceTest, QueryVisits_OldestFirst) { +TEST_F(HistoryClustersServiceTest, QueryVisits_OldestFirst) { // Create 5 persisted visits with visit times 2, 1, 1, 60, and 1 days ago. AddHardcodedTestDataToHistoryService(); @@ -871,11 +838,7 @@ // is from sync, and is still included. const auto [clusters, visits] = NextVisits(continuation_params, false, 0); EXPECT_TRUE(clusters.empty()); - if (ExpectSyncedVisits()) { - EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 3, 2)); - } else { - EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 2)); - } + EXPECT_THAT(GetVisitIds(visits), testing::ElementsAre(5, 3, 2)); EXPECT_TRUE(continuation_params.is_continuation); EXPECT_FALSE(continuation_params.exhausted_unclustered_visits); EXPECT_FALSE(continuation_params.exhausted_all_visits); @@ -890,7 +853,7 @@ } } -TEST_P(HistoryClustersServiceTest, QueryClusteredVisits) { +TEST_F(HistoryClustersServiceTest, QueryClusteredVisits) { // Create unclustered visits 1, 2, 3, and 4 days-old. AddCompleteVisit(1, DaysAgo(1)); AddCompleteVisit(2, DaysAgo(2)); @@ -928,7 +891,7 @@ } } -TEST_P(HistoryClustersServiceTest, EndToEndWithBackend) { +TEST_F(HistoryClustersServiceTest, EndToEndWithBackend) { base::HistogramTester histogram_tester; AddHardcodedTestDataToHistoryService(); @@ -992,7 +955,7 @@ run_loop.Quit(); })); - AwaitAndVerifyTestClusteringBackendRequest(ExpectSyncedVisits()); + AwaitAndVerifyTestClusteringBackendRequest(); std::vector<history::Cluster> clusters; clusters.push_back( @@ -1020,8 +983,7 @@ histogram_tester.ExpectBucketCount( "History.Clusters.Backend.NumClustersReturned", 2, 1); histogram_tester.ExpectBucketCount( - "History.Clusters.Backend.NumVisitsToCluster", - ExpectSyncedVisits() ? 3 : 2, 1); + "History.Clusters.Backend.NumVisitsToCluster", 3, 1); histogram_tester.ExpectTotalCount( "History.Clusters.Backend.GetMostRecentClusters." "ComputeClustersLatency", @@ -1040,7 +1002,7 @@ 0); } -TEST_P(HistoryClustersServiceTest, CompleteVisitContextAnnotationsIfReady) { +TEST_F(HistoryClustersServiceTest, CompleteVisitContextAnnotationsIfReady) { auto test = [&](RecordingStatus status, bool expected_complete) { auto& incomplete_visit_context_annotations = history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations( @@ -1126,7 +1088,7 @@ } } -TEST_P(HistoryClustersServiceTest, +TEST_F(HistoryClustersServiceTest, CompleteVisitContextAnnotationsIfReadyWhenFeatureEnabled) { // When the feature is enabled, the `IncompleteVisitContextAnnotations` // should be removed and added to visits. @@ -1141,8 +1103,7 @@ history_clusters_service_->HasIncompleteVisitContextAnnotations(0)); } -class HistoryClustersServiceKeywordTest - : public HistoryClustersServiceTestBase { +class HistoryClustersServiceKeywordTest : public HistoryClustersServiceTest { public: HistoryClustersServiceKeywordTest() { scoped_feature_list_.InitAndEnableFeature(internal::kJourneys); @@ -1506,7 +1467,7 @@ } class HistoryClustersServiceJourneysDisabledTest - : public HistoryClustersServiceTestBase { + : public HistoryClustersServiceTest { public: HistoryClustersServiceJourneysDisabledTest() { scoped_feature_list_.InitWithFeatures( @@ -1549,7 +1510,7 @@ EXPECT_TRUE(clusters.empty()); } -TEST_F(HistoryClustersServiceTestBase, UpdateClusters_Sparse) { +TEST_F(HistoryClustersServiceTest, UpdateClusters_Sparse) { // Test the case where visits day distribution is wider than // `persist_clusters_recluster_window_days`; i.e. no reclustering occurs. Config config; @@ -1621,7 +1582,7 @@ history::BlockUntilHistoryProcessesPendingRequests(history_service_.get()); } -TEST_F(HistoryClustersServiceTestBase, UpdateClusters_Reclustering) { +TEST_F(HistoryClustersServiceTest, UpdateClusters_Reclustering) { // Test the case where visits day distribution is denser than // `persist_clusters_recluster_window_days`; i.e. reclustering occurs. Config config; @@ -1769,8 +1730,7 @@ history::BlockUntilHistoryProcessesPendingRequests(history_service_.get()); } -TEST_F(HistoryClustersServiceTestBase, - UpdateClusters_ReclusterMultipleClusters) { +TEST_F(HistoryClustersServiceTest, UpdateClusters_ReclusterMultipleClusters) { // Test the case where there are multiple clusters reconsulted in the same // batch. Config config; @@ -1838,7 +1798,7 @@ history::BlockUntilHistoryProcessesPendingRequests(history_service_.get()); } -TEST_F(HistoryClustersServiceTestBase, UpdateClusters_PopularDay) { +TEST_F(HistoryClustersServiceTest, UpdateClusters_PopularDay) { // Test the case there are more visits than `max_visits_to_cluster` in a day. Config config; // TODO(b/276488340): Update this test when non context clusterer code gets
diff --git a/components/history_clusters/core/history_clusters_types.h b/components/history_clusters/core/history_clusters_types.h index dadb7764..896f842 100644 --- a/components/history_clusters/core/history_clusters_types.h +++ b/components/history_clusters/core/history_clusters_types.h
@@ -68,8 +68,10 @@ // Whether to exclude visits that have interaction state equal to hidden. bool filter_hidden_visits = false; - // Whether to include synced visits. - bool include_synced_visits = false; + // Whether to include synced visits. Defaults to true because Full History + // Sync launched in early 2024. But NTP quests is still flag guarding this, + // so this boolean needs to still exist. + bool include_synced_visits = true; // Whether to return merged clusters that are similar based on content. bool group_clusters_by_content = false;
diff --git a/components/history_clusters/core/query_clusters_state.cc b/components/history_clusters/core/query_clusters_state.cc index be537b883..bcea8f0 100644 --- a/components/history_clusters/core/query_clusters_state.cc +++ b/components/history_clusters/core/query_clusters_state.cc
@@ -31,7 +31,8 @@ QueryClustersFilterParams GetFilterParamsFromFlags(const std::string& query) { QueryClustersFilterParams filter_params; - filter_params.include_synced_visits = GetConfig().include_synced_visits; + // Journeys launched Synced visits by default in early 2024. + filter_params.include_synced_visits = true; filter_params.group_clusters_by_content = false; // If there is a query, we do not want to apply any filtering.
diff --git a/components/history_clusters/core/query_clusters_state_unittest.cc b/components/history_clusters/core/query_clusters_state_unittest.cc index 302e324..716973a 100644 --- a/components/history_clusters/core/query_clusters_state_unittest.cc +++ b/components/history_clusters/core/query_clusters_state_unittest.cc
@@ -110,27 +110,10 @@ base::test::TaskEnvironment task_environment_; }; -TEST_F(QueryClustersStateTest, FilterParamsSetForZeroStateSyncedVisits) { - Config config; - config.apply_zero_state_filtering = true; - config.use_navigation_context_clusters = true; - config.include_synced_visits = true; - SetConfigForTesting(config); - - QueryClustersState state(nullptr, nullptr, ""); - - QueryClustersFilterParams filter_params = - GetQueryClustersFilterParamsForState(&state); - EXPECT_TRUE(filter_params.is_search_initiated); - EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_TRUE(filter_params.include_synced_visits); -} - TEST_F(QueryClustersStateTest, FilterParamsSetForZeroState) { Config config; config.apply_zero_state_filtering = true; config.use_navigation_context_clusters = true; - config.include_synced_visits = false; SetConfigForTesting(config); QueryClustersState state(nullptr, nullptr, ""); @@ -139,15 +122,12 @@ GetQueryClustersFilterParamsForState(&state); EXPECT_TRUE(filter_params.is_search_initiated); EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_FALSE(filter_params.include_synced_visits); } -TEST_F(QueryClustersStateTest, - FilterParamsNotSetForZeroStateFeatureDisabledButSyncedVisitsStillSet) { +TEST_F(QueryClustersStateTest, FilterParamsNotSetForZeroStateFeatureDisabled) { Config config; config.apply_zero_state_filtering = false; config.use_navigation_context_clusters = true; - config.include_synced_visits = true; SetConfigForTesting(config); QueryClustersState state(nullptr, nullptr, ""); @@ -156,16 +136,13 @@ GetQueryClustersFilterParamsForState(&state); EXPECT_FALSE(filter_params.is_search_initiated); EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_TRUE(filter_params.include_synced_visits); } -TEST_F( - QueryClustersStateTest, - FilterParamsNotSetForZeroStateContextClusteringDisabledSyncedVisitsStillSet) { +TEST_F(QueryClustersStateTest, + FilterParamsNotSetForZeroStateContextClusteringDisabled) { Config config; config.apply_zero_state_filtering = true; config.use_navigation_context_clusters = false; - config.include_synced_visits = true; SetConfigForTesting(config); QueryClustersState state(nullptr, nullptr, ""); @@ -174,15 +151,12 @@ GetQueryClustersFilterParamsForState(&state); EXPECT_FALSE(filter_params.is_search_initiated); EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_TRUE(filter_params.include_synced_visits); } -TEST_F(QueryClustersStateTest, - FilterParamsEnabledButNotSetForQueryButSyncedVisitsStillSet) { +TEST_F(QueryClustersStateTest, FilterParamsEnabledButNotSetForQuery) { Config config; config.apply_zero_state_filtering = true; config.use_navigation_context_clusters = true; - config.include_synced_visits = true; SetConfigForTesting(config); QueryClustersState state(nullptr, nullptr, "query"); @@ -191,24 +165,6 @@ GetQueryClustersFilterParamsForState(&state); EXPECT_FALSE(filter_params.is_search_initiated); EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_TRUE(filter_params.include_synced_visits); -} - -TEST_F(QueryClustersStateTest, - FilterParamsEnabledButNotSetForQueryButDisabledSyncedVisitsStillSet) { - Config config; - config.apply_zero_state_filtering = true; - config.use_navigation_context_clusters = true; - config.include_synced_visits = false; - SetConfigForTesting(config); - - QueryClustersState state(nullptr, nullptr, "query"); - - QueryClustersFilterParams filter_params = - GetQueryClustersFilterParamsForState(&state); - EXPECT_FALSE(filter_params.is_search_initiated); - EXPECT_FALSE(filter_params.has_related_searches); - EXPECT_FALSE(filter_params.include_synced_visits); } TEST_F(QueryClustersStateTest, PostProcessingOccursAndLogsHistograms) {
diff --git a/components/history_embeddings/history_embeddings_service.cc b/components/history_embeddings/history_embeddings_service.cc index 4b5e364..a4cdf12 100644 --- a/components/history_embeddings/history_embeddings_service.cc +++ b/components/history_embeddings/history_embeddings_service.cc
@@ -149,17 +149,20 @@ nullptr)); } -void HistoryEmbeddingsService::Search(std::string query, - size_t count, - SearchResultCallback callback) { +void HistoryEmbeddingsService::Search( + std::string query, + std::optional<base::Time> time_range_start, + size_t count, + SearchResultCallback callback) { embedder_->ComputePassagesEmbeddings( {std::move(query)}, base::BindOnce(&HistoryEmbeddingsService::OnQueryEmbeddingComputed, - weak_ptr_factory_.GetWeakPtr(), count, + weak_ptr_factory_.GetWeakPtr(), time_range_start, count, std::move(callback))); } void HistoryEmbeddingsService::OnQueryEmbeddingComputed( + std::optional<base::Time> time_range_start, size_t count, SearchResultCallback callback, std::vector<std::string> query_passages, @@ -178,7 +181,7 @@ query_id_++; storage_.AsyncCall(&Storage::Search) .WithArgs(query_id_weak_ptr_factory_.GetWeakPtr(), query_id_.load(), - std::move(query_embeddings.front()), count) + std::move(query_embeddings.front()), time_range_start, count) .Then(base::BindOnce(&HistoryEmbeddingsService::OnSearchCompleted, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); @@ -221,9 +224,10 @@ base::WeakPtr<std::atomic<size_t>> weak_latest_query_id, size_t query_id, Embedding query_embedding, + std::optional<base::Time> time_range_start, size_t count) { std::vector<ScoredUrl> scored_urls = sql_database.FindNearest( - count, std::move(query_embedding), + time_range_start, count, std::move(query_embedding), base::BindRepeating( [](base::WeakPtr<std::atomic<size_t>> weak_latest_query_id, size_t query_id) {
diff --git a/components/history_embeddings/history_embeddings_service.h b/components/history_embeddings/history_embeddings_service.h index 54209a25..752ef71 100644 --- a/components/history_embeddings/history_embeddings_service.h +++ b/components/history_embeddings/history_embeddings_service.h
@@ -6,6 +6,7 @@ #define COMPONENTS_HISTORY_EMBEDDINGS_HISTORY_EMBEDDINGS_SERVICE_H_ #include <atomic> +#include <optional> #include <string> #include <vector> @@ -15,6 +16,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" #include "base/threading/sequence_bound.h" +#include "base/time/time.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" @@ -66,8 +68,14 @@ content::RenderFrameHost& host); // Find top `count` URL visit info entries nearest given `query`. Pass - // results to given `callback` when search completes. - void Search(std::string query, size_t count, SearchResultCallback callback); + // results to given `callback` when search completes. Search will be narrowed + // to a time range if `time_range_start` is provided. In that case, the + // start of the time range is inclusive and the end is unbounded. + // Practically, this can be thought of as [start, now) but now isn't fixed. + void Search(std::string query, + std::optional<base::Time> time_range_start, + size_t count, + SearchResultCallback callback); // Weak `this` provider method. base::WeakPtr<HistoryEmbeddingsService> AsWeakPtr(); @@ -98,6 +106,7 @@ base::WeakPtr<std::atomic<size_t>> weak_latest_query_id, size_t query_id, Embedding query_embedding, + std::optional<base::Time> time_range_start, size_t count); // Handles the History deletions on the worker thread. @@ -123,7 +132,8 @@ // Invoked after the embedding for the original search query has been // computed. - void OnQueryEmbeddingComputed(size_t count, + void OnQueryEmbeddingComputed(std::optional<base::Time> time_range_start, + size_t count, SearchResultCallback callback, std::vector<std::string> query_passages, std::vector<Embedding> query_embedding);
diff --git a/components/history_embeddings/history_embeddings_service_unittest.cc b/components/history_embeddings/history_embeddings_service_unittest.cc index 5ed1947..b2e1772 100644 --- a/components/history_embeddings/history_embeddings_service_unittest.cc +++ b/components/history_embeddings/history_embeddings_service_unittest.cc
@@ -58,7 +58,7 @@ service->storage_.PostTaskWithThisObject(base::BindLambdaForTesting( [&](HistoryEmbeddingsService::Storage* storage) { std::unique_ptr<SqlDatabase::EmbeddingsIterator> iterator = - storage->sql_database.MakeEmbeddingsIterator(); + storage->sql_database.MakeEmbeddingsIterator({}); if (!iterator) { return; }
diff --git a/components/history_embeddings/sql_database.cc b/components/history_embeddings/sql_database.cc index c888a1b..9b00826 100644 --- a/components/history_embeddings/sql_database.cc +++ b/components/history_embeddings/sql_database.cc
@@ -252,9 +252,13 @@ constexpr char kSqlSelectEmbeddings[] = "SELECT url_id, visit_id, visit_time, embeddings_blob FROM embeddings"; +constexpr char kSqlSelectEmbeddingsWithinTimeRange[] = + "SELECT url_id, visit_id, visit_time, embeddings_blob FROM embeddings " + "WHERE visit_time >= ?"; std::unique_ptr<VectorDatabase::EmbeddingsIterator> -SqlDatabase::MakeEmbeddingsIterator() { +SqlDatabase::MakeEmbeddingsIterator( + std::optional<base::Time> time_range_start) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!LazyInit()) { @@ -262,14 +266,24 @@ } DCHECK(db_.IsSQLValid(kSqlSelectEmbeddings)); + DCHECK(db_.IsSQLValid(kSqlSelectEmbeddingsWithinTimeRange)); struct RowEmbeddingsIterator : public EmbeddingsIterator { - explicit RowEmbeddingsIterator(base::WeakPtr<SqlDatabase> sql_database) + explicit RowEmbeddingsIterator(base::WeakPtr<SqlDatabase> sql_database, + std::optional<base::Time> time_range_start) : sql_database(sql_database) { CHECK(!sql_database->iteration_statement_); - sql_database->iteration_statement_ = - std::make_unique<sql::Statement>(sql_database->db_.GetCachedStatement( - SQL_FROM_HERE, kSqlSelectEmbeddings)); + if (time_range_start.has_value()) { + sql_database->iteration_statement_ = std::make_unique<sql::Statement>( + sql_database->db_.GetCachedStatement( + SQL_FROM_HERE, kSqlSelectEmbeddingsWithinTimeRange)); + sql_database->iteration_statement_->BindTime(0, + time_range_start.value()); + } else { + sql_database->iteration_statement_ = std::make_unique<sql::Statement>( + sql_database->db_.GetCachedStatement(SQL_FROM_HERE, + kSqlSelectEmbeddings)); + } } ~RowEmbeddingsIterator() override { if (sql_database) { @@ -308,8 +322,8 @@ UrlEmbeddings data; }; - return std::make_unique<RowEmbeddingsIterator>( - weak_ptr_factory_.GetWeakPtr()); + return std::make_unique<RowEmbeddingsIterator>(weak_ptr_factory_.GetWeakPtr(), + time_range_start); } bool SqlDatabase::DeleteDataForUrlId(history::URLID url_id) {
diff --git a/components/history_embeddings/sql_database.h b/components/history_embeddings/sql_database.h index 97e9c37..45f7ebd 100644 --- a/components/history_embeddings/sql_database.h +++ b/components/history_embeddings/sql_database.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/thread_annotations.h" +#include "base/time/time.h" #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/url_row.h" #include "components/history_embeddings/proto/history_embeddings.pb.h" @@ -47,7 +48,8 @@ // VectorDatabase: size_t GetEmbeddingDimensions() const override; bool AddUrlEmbeddings(const UrlEmbeddings& url_embeddings) override; - std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator() override; + std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator( + std::optional<base::Time> time_range_start) override; // These three methods are used to keep the on-disk persistence in sync with // History deletions, either from user action or time-based expiration.
diff --git a/components/history_embeddings/sql_database_unittest.cc b/components/history_embeddings/sql_database_unittest.cc index 0bf7e88a..def6a0d2 100644 --- a/components/history_embeddings/sql_database_unittest.cc +++ b/components/history_embeddings/sql_database_unittest.cc
@@ -13,6 +13,16 @@ namespace history_embeddings { +namespace { + +Embedding FakeEmbedding() { + Embedding embedding({1.0f, 2.0f, 3.0f, 4.0f}); + embedding.Normalize(); + return embedding; +} + +} // namespace + class HistoryEmbeddingsSqlDatabaseTest : public testing::Test { public: void SetUp() override { @@ -56,7 +66,7 @@ } size_t GetEmbeddingCount(SqlDatabase* sql_database) { - auto iterator = sql_database->MakeEmbeddingsIterator(); + auto iterator = sql_database->MakeEmbeddingsIterator({}); EXPECT_TRUE(iterator); size_t count = 0; while (iterator->Next()) { @@ -99,30 +109,15 @@ TEST_F(HistoryEmbeddingsSqlDatabaseTest, WriteCloseAndThenReadEmbeddings) { auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath()); - // Write embeddings + // Write embeddings. constexpr size_t kCount = 2; UrlEmbeddings url_embeddings[kCount] = { UrlEmbeddings(1, 1, base::Time::Now()), UrlEmbeddings(2, 2, base::Time::Now()), }; - url_embeddings[0].embeddings.push_back(Embedding({ - 1.0f, - 2.0f, - 3.0f, - 4.0f, - })); - url_embeddings[1].embeddings.push_back(Embedding({ - 1.0f, - 2.0f, - 3.0f, - 4.0f, - })); - url_embeddings[1].embeddings.push_back(Embedding({ - 5.0f, - 6.0f, - 7.0f, - 8.0f, - })); + url_embeddings[0].embeddings.push_back(FakeEmbedding()); + url_embeddings[1].embeddings.push_back(FakeEmbedding()); + url_embeddings[1].embeddings.push_back(FakeEmbedding()); EXPECT_TRUE(sql_database->AddUrlEmbeddings(url_embeddings[0])); EXPECT_TRUE(sql_database->AddUrlEmbeddings(url_embeddings[1])); @@ -130,11 +125,11 @@ sql_database.reset(); sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath()); - // Read embeddings + // Read embeddings. { // Block scope destructs iterator before database is closed. std::unique_ptr<VectorDatabase::EmbeddingsIterator> iterator = - sql_database->MakeEmbeddingsIterator(); + sql_database->MakeEmbeddingsIterator({}); EXPECT_TRUE(iterator); for (const UrlEmbeddings& url_embedding : url_embeddings) { const UrlEmbeddings* read_url_embeddings = iterator->Next(); @@ -155,6 +150,59 @@ << "DB file is still there after destruction."; } +TEST_F(HistoryEmbeddingsSqlDatabaseTest, TimeRangeNarrowsSearchResult) { + auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath()); + + // Write embeddings. + const base::Time now = base::Time::Now(); + for (size_t i = 0; i < 3; i++) { + UrlEmbeddings url_embeddings(i + 1, i + 1, now + base::Minutes(i)); + for (size_t j = 0; j < 3; j++) { + url_embeddings.embeddings.push_back(FakeEmbedding()); + } + sql_database->AddUrlEmbeddings(std::move(url_embeddings)); + } + Embedding query = FakeEmbedding(); + + // An ordinary search with full results: + { + std::vector<ScoredUrl> scored_urls = sql_database->FindNearest( + {}, 3, query, base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 3u); + } + + // Narrowed searches with time range. + { + std::vector<ScoredUrl> scored_urls = sql_database->FindNearest( + now, 3, query, base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 3u); + } + { + std::vector<ScoredUrl> scored_urls = + sql_database->FindNearest(now + base::Seconds(30), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 2u); + } + { + std::vector<ScoredUrl> scored_urls = + sql_database->FindNearest(now + base::Seconds(90), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 1u); + } + { + std::vector<ScoredUrl> scored_urls = + sql_database->FindNearest(now + base::Minutes(2), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 1u); + } + { + std::vector<ScoredUrl> scored_urls = + sql_database->FindNearest(now + base::Seconds(121), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 0u); + } +} + TEST_F(HistoryEmbeddingsSqlDatabaseTest, InsertOrReplacePassages) { auto sql_database = std::make_unique<SqlDatabase>(history_dir_.GetPath()); @@ -184,7 +232,7 @@ // Without database reset, iteration reads data. { std::unique_ptr<VectorDatabase::EmbeddingsIterator> iterator = - sql_database->MakeEmbeddingsIterator(); + sql_database->MakeEmbeddingsIterator({}); EXPECT_TRUE(iterator); EXPECT_TRUE(iterator->Next()); } @@ -192,7 +240,7 @@ // With database reset, iteration gracefully ends. { std::unique_ptr<VectorDatabase::EmbeddingsIterator> iterator = - sql_database->MakeEmbeddingsIterator(); + sql_database->MakeEmbeddingsIterator({}); EXPECT_TRUE(iterator); // Reset database while iterator is still in scope.
diff --git a/components/history_embeddings/vector_database.cc b/components/history_embeddings/vector_database.cc index a3e32d52..7188acf 100644 --- a/components/history_embeddings/vector_database.cc +++ b/components/history_embeddings/vector_database.cc
@@ -99,6 +99,7 @@ //////////////////////////////////////////////////////////////////////////////// std::vector<ScoredUrl> VectorDatabase::FindNearest( + std::optional<base::Time> time_range_start, size_t count, const Embedding& query, base::RepeatingCallback<bool()> is_search_halted) { @@ -106,7 +107,8 @@ return {}; } - std::unique_ptr<EmbeddingsIterator> iterator = MakeEmbeddingsIterator(); + std::unique_ptr<EmbeddingsIterator> iterator = + MakeEmbeddingsIterator(time_range_start); if (!iterator) { return {}; } @@ -183,13 +185,27 @@ } std::unique_ptr<VectorDatabase::EmbeddingsIterator> -VectorDatabaseInMemory::MakeEmbeddingsIterator() { +VectorDatabaseInMemory::MakeEmbeddingsIterator( + std::optional<base::Time> time_range_start) { struct SimpleEmbeddingsIterator : public EmbeddingsIterator { - explicit SimpleEmbeddingsIterator(const std::vector<UrlEmbeddings>& source) - : iterator_(source.cbegin()), end_(source.cend()) {} + explicit SimpleEmbeddingsIterator( + const std::vector<UrlEmbeddings>& source, + std::optional<base::Time> time_range_start) + : iterator_(source.cbegin()), + end_(source.cend()), + time_range_start_(time_range_start) {} ~SimpleEmbeddingsIterator() override = default; const UrlEmbeddings* Next() override { + if (time_range_start_.has_value()) { + while (iterator_ != end_) { + if (iterator_->visit_time >= time_range_start_.value()) { + break; + } + iterator_++; + } + } + if (iterator_ == end_) { return nullptr; } @@ -198,13 +214,14 @@ std::vector<UrlEmbeddings>::const_iterator iterator_; std::vector<UrlEmbeddings>::const_iterator end_; + const std::optional<base::Time> time_range_start_; }; if (data_.empty()) { return nullptr; } - return std::make_unique<SimpleEmbeddingsIterator>(data_); + return std::make_unique<SimpleEmbeddingsIterator>(data_, time_range_start); } } // namespace history_embeddings
diff --git a/components/history_embeddings/vector_database.h b/components/history_embeddings/vector_database.h index c35d8d4..fbffd508 100644 --- a/components/history_embeddings/vector_database.h +++ b/components/history_embeddings/vector_database.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_HISTORY_EMBEDDINGS_VECTOR_DATABASE_H_ #define COMPONENTS_HISTORY_EMBEDDINGS_VECTOR_DATABASE_H_ +#include <optional> #include <vector> #include "base/time/time.h" @@ -124,11 +125,13 @@ // Create an iterator that steps through database items. // Null may be returned if there are none. - virtual std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator() = 0; + virtual std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator( + std::optional<base::Time> time_range_start) = 0; // Searches the database for embeddings near given `query` and returns // information about where they were found and how nearly the query matched. std::vector<ScoredUrl> FindNearest( + std::optional<base::Time> time_range_start, size_t count, const Embedding& query, base::RepeatingCallback<bool()> is_search_halted); @@ -149,7 +152,8 @@ // VectorDatabase: size_t GetEmbeddingDimensions() const override; bool AddUrlEmbeddings(const UrlEmbeddings& url_embeddings) override; - std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator() override; + std::unique_ptr<EmbeddingsIterator> MakeEmbeddingsIterator( + std::optional<base::Time> time_range_start) override; private: std::vector<UrlEmbeddings> data_;
diff --git a/components/history_embeddings/vector_database_unittest.cc b/components/history_embeddings/vector_database_unittest.cc index 8411e9c..a3fe931b 100644 --- a/components/history_embeddings/vector_database_unittest.cc +++ b/components/history_embeddings/vector_database_unittest.cc
@@ -62,7 +62,7 @@ // An ordinary search with full results: { std::vector<ScoredUrl> scored_urls = database.FindNearest( - 3, query, base::BindRepeating([]() { return false; })); + {}, 3, query, base::BindRepeating([]() { return false; })); CHECK_EQ(scored_urls.size(), 3u); } @@ -71,7 +71,7 @@ std::atomic<size_t> counter(0u); base::WeakPtrFactory<std::atomic<size_t>> weak_factory(&counter); std::vector<ScoredUrl> scored_urls = - database.FindNearest(3, query, + database.FindNearest({}, 3, query, base::BindRepeating( [](auto weak_counter) { (*weak_counter)++; @@ -82,6 +82,57 @@ } } +TEST(HistoryEmbeddingsVectorDatabaseTest, TimeRangeNarrowsSearchResult) { + const base::Time now = base::Time::Now(); + VectorDatabaseInMemory database; + for (size_t i = 0; i < 3; i++) { + UrlEmbeddings url_embeddings(i + 1, i + 1, now + base::Minutes(i)); + for (size_t j = 0; j < 3; j++) { + url_embeddings.embeddings.push_back(RandomEmbedding()); + } + database.AddUrlEmbeddings(std::move(url_embeddings)); + } + Embedding query = RandomEmbedding(); + + // An ordinary search with full results: + { + std::vector<ScoredUrl> scored_urls = database.FindNearest( + {}, 3, query, base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 3u); + } + + // Narrowed searches with time range. + { + std::vector<ScoredUrl> scored_urls = database.FindNearest( + now, 3, query, base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 3u); + } + { + std::vector<ScoredUrl> scored_urls = + database.FindNearest(now + base::Seconds(30), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 2u); + } + { + std::vector<ScoredUrl> scored_urls = + database.FindNearest(now + base::Seconds(90), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 1u); + } + { + std::vector<ScoredUrl> scored_urls = + database.FindNearest(now + base::Minutes(2), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 1u); + } + { + std::vector<ScoredUrl> scored_urls = + database.FindNearest(now + base::Seconds(121), 3, query, + base::BindRepeating([]() { return false; })); + CHECK_EQ(scored_urls.size(), 0u); + } +} + // Note: Disabled by default so as to not burden the bots. Enable when needed. TEST(HistoryEmbeddingsVectorDatabaseTest, DISABLED_ManyVectorsAreFastEnough) { VectorDatabaseInMemory database; @@ -103,7 +154,7 @@ std::atomic<size_t> id(0u); base::WeakPtrFactory<std::atomic<size_t>> weak_factory(&id); database.FindNearest( - 3, query, + {}, 3, query, base::BindRepeating( [](auto weak_id) { return !weak_id || *weak_id != 0u; }, weak_factory.GetWeakPtr()));
diff --git a/components/media_router/common/providers/cast/certificate/BUILD.gn b/components/media_router/common/providers/cast/certificate/BUILD.gn index da6d7103b..02ca68b 100644 --- a/components/media_router/common/providers/cast/certificate/BUILD.gn +++ b/components/media_router/common/providers/cast/certificate/BUILD.gn
@@ -31,6 +31,8 @@ "cast_cert_validator.h", "cast_crl.cc", "cast_crl.h", + "cast_trust_store.cc", + "cast_trust_store.h", "switches.cc", "switches.h", ]
diff --git a/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.cc b/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.cc index cb20f7f..6732b6e 100644 --- a/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.cc +++ b/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.cc
@@ -6,10 +6,12 @@ #include "base/base_paths.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/no_destructor.h" #include "base/path_service.h" #include "base/threading/thread_restrictions.h" #include "components/media_router/common/providers/cast/certificate/cast_cert_reader.h" +#include "components/media_router/common/providers/cast/certificate/cast_trust_store.h" #include "net/cert/x509_util.h" #include "third_party/boringssl/src/pki/cert_errors.h" #include "third_party/boringssl/src/pki/pem.h" @@ -96,9 +98,60 @@ auto store = std::make_unique<bssl::TrustStoreInMemory>(); CHECK(PopulateStoreWithCertsFromPath( store.get(), - testing::GetCastCertificatesSubDirectory().AppendASCII(cert_file_name))); + GetCastCertificatesSubDirectory().AppendASCII(cert_file_name))); CHECK(store); return store; } + +// static +std::atomic_flag ScopedCastTrustStoreConfig::in_use_ = ATOMIC_FLAG_INIT; + +void ScopedCastTrustStoreConfig::SetInUse() { + const bool previous_value = in_use_.test_and_set(std::memory_order_relaxed); + CHECK(!previous_value) << "Unable to create ScopedCastTrustStoreConfig: " + "there is another instance that is active."; +} + +std::unique_ptr<ScopedCastTrustStoreConfig> +ScopedCastTrustStoreConfig::BuiltInCertificates() { + SetInUse(); + CastTrustStore* store = CastTrustStore::GetInstance(/*may_block=*/true); + store->ClearCertificatesForTesting(); + store->AddBuiltInCertificates(); + return std::make_unique<ScopedCastTrustStoreConfig>(); +} + +std::unique_ptr<ScopedCastTrustStoreConfig> +ScopedCastTrustStoreConfig::TestCertificates( + const std::string_view& cert_file_name) { + SetInUse(); + const auto cert_path = + GetCastCertificatesSubDirectory().AppendASCII(cert_file_name); + CastTrustStore* store = CastTrustStore::GetInstance(/*may_block=*/true); + store->ClearCertificatesForTesting(); + store->AddCertificateFromPath(cert_path); + return std::make_unique<ScopedCastTrustStoreConfig>(); +} + +std::unique_ptr<ScopedCastTrustStoreConfig> +ScopedCastTrustStoreConfig::BuiltInAndTestCertificates( + const std::string_view& cert_file_name) { + SetInUse(); + const auto cert_path = + GetCastCertificatesSubDirectory().AppendASCII(cert_file_name); + CastTrustStore* store = CastTrustStore::GetInstance(/*may_block=*/true); + store->ClearCertificatesForTesting(); + store->AddBuiltInCertificates(); + store->AddCertificateFromPath(cert_path); + return std::make_unique<ScopedCastTrustStoreConfig>(); +} + +ScopedCastTrustStoreConfig::~ScopedCastTrustStoreConfig() { + CastTrustStore* store = CastTrustStore::GetInstance(/*may_block=*/true); + store->ClearCertificatesForTesting(); + store->AddDefaultCertificates(/*may_block=*/true); + in_use_.clear(); +} + } // namespace testing } // namespace cast_certificate
diff --git a/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.h b/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.h index 2216167..a27a6e2e 100644 --- a/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.h +++ b/components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_CERT_TEST_HELPERS_H_ #define COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_CERT_TEST_HELPERS_H_ +#include <atomic> #include <memory> #include <string> @@ -49,6 +50,38 @@ std::unique_ptr<bssl::TrustStoreInMemory> LoadTestCert( const base::StringPiece& cert_file_name); +// This allows for modifying the CastTrustStore in order to run a test. When +// the instance is destroyed, the CastTrustStore will be reverted to its +// default state. Used for testing. +class ScopedCastTrustStoreConfig { + public: + // Note: There is no need for a default config. Calling VerifyDeviceCert() + // without a ScopedCastTrustStoreConfig instance present will use the + // default configuration. + static std::unique_ptr<ScopedCastTrustStoreConfig> BuiltInCertificates(); + static std::unique_ptr<ScopedCastTrustStoreConfig> TestCertificates( + const std::string_view& cert_file_name); + static std::unique_ptr<ScopedCastTrustStoreConfig> BuiltInAndTestCertificates( + const std::string_view& cert_file_name); + ScopedCastTrustStoreConfig(const ScopedCastTrustStoreConfig&) = delete; + ScopedCastTrustStoreConfig& operator=(const ScopedCastTrustStoreConfig&) = + delete; + ~ScopedCastTrustStoreConfig(); + + private: + friend std::unique_ptr<ScopedCastTrustStoreConfig> + std::make_unique<ScopedCastTrustStoreConfig>(); + ScopedCastTrustStoreConfig() = default; + + // Sets the `in_use_` singleton and checks that there are no other + // ScopedCastTrustStoreConfig instances. + static void SetInUse(); + + // Tracks whether or not there is an instance globally in the process. This is + // used to ensure that there is not more than one instance at any given time. + static std::atomic_flag in_use_; +}; + } // namespace testing } // namespace cast_certificate
diff --git a/components/media_router/common/providers/cast/certificate/cast_cert_validator.cc b/components/media_router/common/providers/cast/certificate/cast_cert_validator.cc index 669dc71f..9c04ab2 100644 --- a/components/media_router/common/providers/cast/certificate/cast_cert_validator.cc +++ b/components/media_router/common/providers/cast/certificate/cast_cert_validator.cc
@@ -15,16 +15,13 @@ #include "base/containers/contains.h" #include "base/containers/span.h" #include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "base/no_destructor.h" #include "base/path_service.h" #include "base/strings/string_piece.h" -#include "base/synchronization/lock.h" #include "base/task/task_traits.h" -#include "base/task/thread_pool.h" #include "components/media_router/common/providers/cast/certificate/cast_cert_printer.h" #include "components/media_router/common/providers/cast/certificate/cast_cert_reader.h" #include "components/media_router/common/providers/cast/certificate/cast_crl.h" +#include "components/media_router/common/providers/cast/certificate/cast_trust_store.h" #include "components/media_router/common/providers/cast/certificate/switches.h" #include "net/cert/time_conversions.h" #include "net/cert/x509_util.h" @@ -35,9 +32,7 @@ #include "third_party/boringssl/src/pki/certificate_policies.h" #include "third_party/boringssl/src/pki/common_cert_errors.h" #include "third_party/boringssl/src/pki/input.h" -#include "third_party/boringssl/src/pki/parse_certificate.h" #include "third_party/boringssl/src/pki/parse_name.h" -#include "third_party/boringssl/src/pki/parsed_certificate.h" #include "third_party/boringssl/src/pki/path_builder.h" #include "third_party/boringssl/src/pki/simple_path_builder_delegate.h" #include "third_party/boringssl/src/pki/trust_store_in_memory.h" @@ -49,103 +44,6 @@ case x: \ return #x; -// ------------------------------------------------------------------------- -// Cast trust anchors. -// ------------------------------------------------------------------------- - -// There are two trusted roots for Cast certificate chains: -// -// (1) CN=Cast Root CA (kCastRootCaDer) -// (2) CN=Eureka Root CA (kEurekaRootCaDer) -// -// These constants are defined by the files included next: - -#include "components/media_router/common/providers/cast/certificate/cast_root_ca_cert_der-inc.h" -#include "components/media_router/common/providers/cast/certificate/eureka_root_ca_der-inc.h" - -class CastTrustStore { - public: - using AccessCallback = base::OnceCallback<void(bssl::TrustStore*)>; - - CastTrustStore(const CastTrustStore&) = delete; - CastTrustStore& operator=(const CastTrustStore&) = delete; - - static void AccessInstance(AccessCallback callback) { - CastTrustStore* instance = GetInstance(); - const base::AutoLock guard(instance->lock_); - std::move(callback).Run(&instance->store_); - } - - private: - friend class base::NoDestructor<CastTrustStore>; - - static CastTrustStore* GetInstance() { - static base::NoDestructor<CastTrustStore> instance; - return instance.get(); - } - - CastTrustStore() { - AddAnchor(kCastRootCaDer); - AddAnchor(kEurekaRootCaDer); - - auto developer_cert_path = GetDeveloperCertificatePathFromCommandLine(); - if (!developer_cert_path.empty()) { - // Adding developer certificates must be done off of the IO thread due - // to blocking file access. - base::ThreadPool::PostTask( - FROM_HERE, {base::MayBlock()}, - // NOTE: the singleton instance is never destroyed, so we can use - // Unretained here instead of a weak pointer. - base::BindOnce(&CastTrustStore::AddDeveloperCertificate, - base::Unretained(this), - std::move(developer_cert_path))); - } - } - - // Returns the cast developer certificate path command line switch if it is - // set. Otherwise, returns an empty file path. - static base::FilePath GetDeveloperCertificatePathFromCommandLine() { - auto* command_line = base::CommandLine::ForCurrentProcess(); - return command_line->GetSwitchValuePath( - switches::kCastDeveloperCertificatePath); - } - - // Create a trust store from custom root developer certificate - void AddDeveloperCertificate(base::FilePath cert_path) { - base::AutoLock guard(lock_); - if (!cert_path.IsAbsolute()) { - base::FilePath path; - base::PathService::Get(base::DIR_CURRENT, &path); - cert_path = path.Append(cert_path); - } - VLOG(1) << "Using cast developer certificate path " << cert_path; - if (!PopulateStoreWithCertsFromPath(&store_, cert_path)) { - LOG(WARNING) << "Unable to add Cast developer certificates at " - << cert_path - << " to Cast root store; only Google-provided Cast root " - "certificates will be used."; - } - } - - // Adds a trust anchor given a DER-encoded certificate from static - // storage. - template <size_t N> - void AddAnchor(const uint8_t (&data)[N]) { - bssl::CertErrors errors; - std::shared_ptr<const bssl::ParsedCertificate> cert = - bssl::ParsedCertificate::Create( - net::x509_util::CreateCryptoBufferFromStaticDataUnsafe(data), {}, - &errors); - CHECK(cert) << errors.ToDebugString(); - // Enforce pathlen constraints and policies defined on the root certificate. - base::AutoLock guard(lock_); - store_.AddTrustAnchorWithConstraints(std::move(cert)); - } - - base::Lock lock_; - bssl::TrustStoreInMemory store_ GUARDED_BY(lock_); -}; - // Returns the OID for the Audio-Only Cast policy // (1.3.6.1.4.1.11129.2.5.2) in DER form. bssl::der::Input AudioOnlyPolicyOid() {
diff --git a/components/media_router/common/providers/cast/certificate/cast_cert_validator.h b/components/media_router/common/providers/cast/certificate/cast_cert_validator.h index a760d06a..e6acae6 100644 --- a/components/media_router/common/providers/cast/certificate/cast_cert_validator.h +++ b/components/media_router/common/providers/cast/certificate/cast_cert_validator.h
@@ -5,10 +5,12 @@ #ifndef COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_CERT_VALIDATOR_H_ #define COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_CERT_VALIDATOR_H_ +#include <atomic> #include <memory> #include <string> #include <vector> +#include "base/files/file_path.h" #include "base/strings/string_piece.h" #include "base/time/time.h" @@ -107,7 +109,13 @@ virtual std::string GetCommonName() const = 0; }; -// Verifies a cast device certficate given a chain of DER-encoded certificates, +// These provide access for tests to change the CastTrustStoreSingleton. +void CastTrustStoreAddDefaultCertificatesForTesting(); +void CastTrustStoreAddBuiltInCertificatesForTesting(); +void CastTrustStoreAddCertificateFromPathForTesting(base::FilePath cert_path); +void CastTrustStoreClearForTesting(); + +// Verifies a cast device certificate given a chain of DER-encoded certificates, // using the built-in Cast trust anchors. // // Inputs: @@ -144,6 +152,7 @@ std::unique_ptr<CertVerificationContext>* context, CastDeviceCertPolicy* policy, const CastCRL* crl, + const CastCRL* fallback_crl, CRLPolicy crl_policy); // This is an overloaded version of VerifyDeviceCert that allows
diff --git a/components/media_router/common/providers/cast/certificate/cast_cert_validator_unittest.cc b/components/media_router/common/providers/cast/certificate/cast_cert_validator_unittest.cc index f0bc11e..516b125a 100644 --- a/components/media_router/common/providers/cast/certificate/cast_cert_validator_unittest.cc +++ b/components/media_router/common/providers/cast/certificate/cast_cert_validator_unittest.cc
@@ -6,10 +6,12 @@ #include <memory> +#include "base/command_line.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/media_router/common/providers/cast/certificate/cast_cert_reader.h" #include "components/media_router/common/providers/cast/certificate/cast_cert_test_helpers.h" +#include "components/media_router/common/providers/cast/certificate/switches.h" #include "net/cert/x509_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/boringssl/src/pki/cert_errors.h" @@ -32,6 +34,11 @@ // verified in production. TRUST_STORE_BUILTIN, + // Uses the built-in trust store for Cast. However also load a + // developer-signed certificate file. This is how certificates are verified if + // the --cast_developer_certificates_path command line option is set. + TRUST_STORE_BUILTIN_WITH_DEVELOPER_CERTIFICATE_PATH, + // Instead of using the built-in trust store, use root certificate in the // provided test chain as the trust anchor. // @@ -45,6 +52,10 @@ TRUST_STORE_FROM_TEST_FILE_UNCONSTRAINED, }; +// Used for TRUST_STORE_BUILTIN_WITH_DEVELOPER_CERTIFICATE_PATH mode. +const std::string kDeveloperSignedCertificateFile = + "generated_root_cast_receiver.pem"; + // Reads a test chain from |certs_file_name|, and asserts that verifying it as // a Cast device certificate yields |expected_result|. // @@ -71,10 +82,24 @@ testing::GetCastCertificatesSubDirectory().AppendASCII(certs_file_name)); std::unique_ptr<bssl::TrustStoreInMemory> trust_store; + std::unique_ptr<testing::ScopedCastTrustStoreConfig> scoped_cast_trust_store; switch (trust_store_dependency) { case TRUST_STORE_BUILTIN: // Leave trust_store as nullptr. + scoped_cast_trust_store = + testing::ScopedCastTrustStoreConfig::BuiltInCertificates(); + ASSERT_NE(scoped_cast_trust_store, nullptr); + break; + + case TRUST_STORE_BUILTIN_WITH_DEVELOPER_CERTIFICATE_PATH: + // Leave trust_store as nullptr. + // Use the developer-signed certificate file: + // kDeveloperSignedCertificateFile. + scoped_cast_trust_store = + testing::ScopedCastTrustStoreConfig::BuiltInAndTestCertificates( + kDeveloperSignedCertificateFile); + ASSERT_NE(scoped_cast_trust_store, nullptr); break; case TRUST_STORE_FROM_TEST_FILE: @@ -198,6 +223,25 @@ // Tests verifying a valid certificate chain of length 2: // +// 0: 2ZZBG9 FA8FCA3EF91A +// 1: Eureka Gen1 ICA +// +// Chains to trust anchor: +// Eureka Root CA (built-in trust store) +// +// The trust store loads a developer-signed certificate to emulate running +// with the --cast_developer_certificate_path command line flag. The device +// does not use the root of trust from the loaded certificate. +TEST(VerifyCastDeviceCertTest, + BuiltInTrustDeviceWithUnusedDeveloperCertificatePathLoaded) { + RunTest(CastCertError::OK, "2ZZBG9 FA8FCA3EF91A", CastDeviceCertPolicy::NONE, + "chromecast_gen1.pem", AprilFirst2016(), + TRUST_STORE_BUILTIN_WITH_DEVELOPER_CERTIFICATE_PATH, + "signeddata/2ZZBG9_FA8FCA3EF91A.pem"); +} + +// Tests verifying a valid certificate chain of length 2: +// // 0: 2ZZBG9 FA8FCA3EF91A // 1: Eureka Gen1 ICA // @@ -234,6 +278,21 @@ "fugu.pem", AprilFirst2016(), TRUST_STORE_BUILTIN, ""); } +// Tests verifying a developer signed certificate that is provided via the +// command line flag: --cast_developer_certificates_path. +// +// 0: Cast Root CA +// +// Chains to trust anchor: +// Cast Root CA (built-in trust store) +// +// Chains to trust anchor: +TEST(VerifyCastDeviceCertTest, DeviceMatchingCastDeveloperCertificatePath) { + RunTest(CastCertError::OK, "Cast Root CA", CastDeviceCertPolicy::NONE, + kDeveloperSignedCertificateFile, CreateDate(2024, 4, 4), + TRUST_STORE_BUILTIN_WITH_DEVELOPER_CERTIFICATE_PATH, ""); +} + // Tests verifying an invalid certificate chain of length 1: // // 0: Cast Test Untrusted Device
diff --git a/components/media_router/common/providers/cast/certificate/cast_trust_store.cc b/components/media_router/common/providers/cast/certificate/cast_trust_store.cc new file mode 100644 index 0000000..7d4c0304 --- /dev/null +++ b/components/media_router/common/providers/cast/certificate/cast_trust_store.cc
@@ -0,0 +1,140 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/media_router/common/providers/cast/certificate/cast_trust_store.h" + +#include <stddef.h> +#include <stdint.h> + +#include <memory> +#include <utility> + +#include "base/command_line.h" +#include "base/functional/bind.h" +#include "base/logging.h" +#include "base/no_destructor.h" +#include "base/path_service.h" +#include "base/synchronization/lock.h" +#include "base/task/thread_pool.h" +#include "components/media_router/common/providers/cast/certificate/cast_cert_reader.h" +#include "components/media_router/common/providers/cast/certificate/switches.h" +#include "net/cert/x509_util.h" +#include "third_party/boringssl/src/pki/common_cert_errors.h" +#include "third_party/boringssl/src/pki/parse_certificate.h" +#include "third_party/boringssl/src/pki/parsed_certificate.h" +#include "third_party/boringssl/src/pki/trust_store_in_memory.h" + +namespace cast_certificate { +namespace { +// Returns a DER-encoded certificate from static storage. +template <size_t N> +std::shared_ptr<const bssl::ParsedCertificate> +ParseCertificateFromStaticStorage(const uint8_t (&data)[N]) { + bssl::CertErrors errors; + std::shared_ptr<const bssl::ParsedCertificate> cert = + bssl::ParsedCertificate::Create( + net::x509_util::CreateCryptoBufferFromStaticDataUnsafe(data), {}, + &errors); + CHECK(cert) << errors.ToDebugString(); + return cert; +} + +// Returns the cast developer certificate path command line switch if it is +// set. Otherwise, returns an empty file path. +base::FilePath GetDeveloperCertificatePathFromCommandLine() { + auto* command_line = base::CommandLine::ForCurrentProcess(); + return command_line->GetSwitchValuePath( + switches::kCastDeveloperCertificatePath); +} +} // namespace + +void CastTrustStore::AccessInstance(CastTrustStore::AccessCallback callback) { + CastTrustStore* instance = GetInstance(); + const base::AutoLock guard(instance->lock_); + std::move(callback).Run(&instance->store_); +} + +CastTrustStore* CastTrustStore::GetInstance(bool may_block) { + static base::NoDestructor<CastTrustStore> instance(may_block); + return instance.get(); +} + +CastTrustStore::CastTrustStore(bool may_block) { + AddDefaultCertificates(may_block); +} + +void CastTrustStore::AddDefaultCertificates(bool may_block) { + AddBuiltInCertificates(); + + // Checks to see if there is a developer certificate path was set on the + // command line. If so, it should be loaded and added to the trust store. + auto developer_cert_path = GetDeveloperCertificatePathFromCommandLine(); + if (!developer_cert_path.empty()) { + if (may_block) { + AddCertificateFromPath(developer_cert_path); + } else { + NonBlockingAddCertificateFromPath(developer_cert_path); + } + } +} + +// ------------------------------------------------------------------------- +// Cast trust anchors. +// ------------------------------------------------------------------------- + +// There are two trusted roots for Cast certificate chains: +// +// (1) CN=Cast Root CA (kCastRootCaDer) +// (2) CN=Eureka Root CA (kEurekaRootCaDer) +// +// These constants are defined by the files included next: + +#include "components/media_router/common/providers/cast/certificate/cast_root_ca_cert_der-inc.h" +#include "components/media_router/common/providers/cast/certificate/eureka_root_ca_der-inc.h" + +void CastTrustStore::AddBuiltInCertificates() { + AddAnchor(ParseCertificateFromStaticStorage(kCastRootCaDer)); + AddAnchor(ParseCertificateFromStaticStorage(kEurekaRootCaDer)); +} + +void CastTrustStore::NonBlockingAddCertificateFromPath( + base::FilePath cert_path) { + // Adding developer certificates must be done off of the IO thread due + // to blocking file access. + base::ThreadPool::PostTask( + FROM_HERE, {base::MayBlock()}, + // NOTE: the singleton instance is never destroyed, so we can use + // Unretained here instead of a weak pointer. + base::BindOnce(&CastTrustStore::AddCertificateFromPath, + base::Unretained(this), std::move(cert_path))); +} + +void CastTrustStore::AddCertificateFromPath(base::FilePath cert_path) { + if (!cert_path.IsAbsolute()) { + base::FilePath path; + base::PathService::Get(base::DIR_CURRENT, &path); + cert_path = path.Append(cert_path); + } + VLOG(1) << "Using cast developer certificate path " << cert_path; + base::AutoLock guard(lock_); + if (!PopulateStoreWithCertsFromPath(&store_, cert_path)) { + LOG(WARNING) << "Unable to add Cast developer certificates at " << cert_path + << " to Cast root store; only Google-provided Cast root " + "certificates will be used."; + } +} + +void CastTrustStore::ClearCertificatesForTesting() { + base::AutoLock guard(lock_); + store_.Clear(); +} + +void CastTrustStore::AddAnchor( + std::shared_ptr<const bssl::ParsedCertificate> cert) { + // Enforce pathlen constraints and policies defined on the root certificate. + base::AutoLock guard(lock_); + store_.AddTrustAnchorWithConstraints(std::move(cert)); +} + +} // namespace cast_certificate
diff --git a/components/media_router/common/providers/cast/certificate/cast_trust_store.h b/components/media_router/common/providers/cast/certificate/cast_trust_store.h new file mode 100644 index 0000000..61bd7f2 --- /dev/null +++ b/components/media_router/common/providers/cast/certificate/cast_trust_store.h
@@ -0,0 +1,79 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_TRUST_STORE_H_ +#define COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_TRUST_STORE_H_ + +#include <memory> +#include <string> + +#include "base/files/file_path.h" +#include "base/functional/callback.h" +#include "base/no_destructor.h" +#include "base/synchronization/lock.h" +#include "base/time/time.h" +#include "third_party/boringssl/src/pki/trust_store_in_memory.h" + +namespace bssl { +class TrustStore; +class TrustStore; +class ParsedCertificate; +} // namespace bssl +namespace cast_certificate { +namespace testing { +class ScopedCastTrustStoreConfig; +} // namespace testing + +class CastTrustStore { + public: + using AccessCallback = base::OnceCallback<void(bssl::TrustStore*)>; + + CastTrustStore(const CastTrustStore&) = delete; + CastTrustStore(CastTrustStore&&) = delete; + CastTrustStore& operator=(const CastTrustStore&) = delete; + CastTrustStore& operator=(CastTrustStore&&) = delete; + + static void AccessInstance(AccessCallback callback); + + private: + friend class base::NoDestructor<CastTrustStore>; + friend class cast_certificate::testing::ScopedCastTrustStoreConfig; + + // GetInstance() provides access to the trust store singleton `instance`. + // `instance` is constructed at the first call to the function. Callers should + // run with `may_block`=false (or unspecified), if calling from an IO thread + // to let the constructor defer loading of a developer certificate path to + // another thread. + static CastTrustStore* GetInstance(bool may_block = false); + + explicit CastTrustStore(bool may_block); + + // AddDefaultCertificates() is called by the constructor. It adds the built-in + // certificates to `store_`. If developer certificates are specified on the + // command line, then they are loaded from file. + void AddDefaultCertificates(bool may_block); + + // Adds the built-in Chrome certificates from memory. + void AddBuiltInCertificates(); + + // Adding developer certificates may need to be done off of the IO thread due + // to blocking file access. + void NonBlockingAddCertificateFromPath(base::FilePath cert_path); + + // Loads certificates from `cert_path` and adds them to the trust store. + void AddCertificateFromPath(base::FilePath cert_path); + + // Clears certificates in `store_`. For use in testing. + void ClearCertificatesForTesting(); + + // Adds a trust anchor from a parsed certificate. + void AddAnchor(std::shared_ptr<const bssl::ParsedCertificate> cert); + + base::Lock lock_; + bssl::TrustStoreInMemory store_ GUARDED_BY(lock_); +}; + +} // namespace cast_certificate + +#endif // COMPONENTS_MEDIA_ROUTER_COMMON_PROVIDERS_CAST_CERTIFICATE_CAST_TRUST_STORE_H_
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc index ef7ba12..ab0942d 100644 --- a/components/omnibox/browser/clipboard_provider.cc +++ b/components/omnibox/browser/clipboard_provider.cc
@@ -583,7 +583,7 @@ match.search_terms_args = std::make_unique<TemplateURLRef::SearchTermsArgs>(u""); match.search_terms_args->image_thumbnail_content.assign( - image_bytes->front_as<char>(), image_bytes->size()); + base::as_string_view(*image_bytes)); TemplateURLRef::PostContent post_content; GURL result(default_url->image_url_ref().ReplaceSearchTerms( *match.search_terms_args.get(), url_service->search_terms_data(),
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc index beb421f0..bcc30594 100644 --- a/components/omnibox/browser/history_url_provider_unittest.cc +++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -42,6 +42,7 @@ #include "third_party/metrics_proto/omnibox_focus_type.pb.h" #include "third_party/metrics_proto/omnibox_input_type.pb.h" #include "ui/base/page_transition_types.h" +#include "url/url_features.h" using base::ASCIIToUTF16; using base::Time; @@ -1137,7 +1138,30 @@ std::size(expected_when_searching_site)); } -TEST_F(HistoryURLProviderTest, SuggestExactInput) { +// Non-special URLs behavior is affected by the +// StandardCompliantNonSpecialSchemeURLParsing feature. +// See https://crbug.com/40063064 for details. +class HistoryURLProviderParamTest : public HistoryURLProviderTest, + public ::testing::WithParamInterface<bool> { + public: + HistoryURLProviderParamTest() + : use_standard_compliant_non_special_scheme_url_parsing_(GetParam()) { + if (use_standard_compliant_non_special_scheme_url_parsing_) { + scoped_feature_list_.InitAndEnableFeature( + url::kStandardCompliantNonSpecialSchemeURLParsing); + } else { + scoped_feature_list_.InitAndDisableFeature( + url::kStandardCompliantNonSpecialSchemeURLParsing); + } + } + + bool use_standard_compliant_non_special_scheme_url_parsing_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_P(HistoryURLProviderParamTest, SuggestExactInput) { const size_t npos = std::string::npos; struct TestCase { // Inputs: @@ -1150,8 +1174,12 @@ // The index of the ACMatchClassification that should have the MATCH bit // set, npos if no ACMatchClassification should have the MATCH bit set. size_t match_classification_index; + // Expected outputs when StandardCompliantNonSpecialSchemeURLParsing feature + // is enabled. This field can be omitted if the expected output remains + // the same regardless of the feature being enabled. + const char* contents_when_non_special_url_feature_is_enabled; } test_cases[] = { - // clang-format off + // clang-format off { "http://www.somesite.com", false, "http://www.somesite.com", {0, npos, npos}, 0 }, { "http://www.somesite.com/", false, @@ -1182,10 +1210,12 @@ "http://www.w.com", {0, npos, npos}, 0 }, { "http://a///www.w.com", false, "http://a///www.w.com", {0, npos, npos}, 0 }, + { "http://a@b.com", false, "http://b.com", {0, npos, npos}, 0 }, + { "a@b.com", true, "b.com", {0, npos, npos} }, { "mailto://a@b.com", true, - "mailto://a@b.com", {0, npos, npos}, 0 }, + "mailto://a@b.com", {0, npos, npos}, 0, "mailto://b.com" }, { "mailto://a@b.com", false, - "mailto://a@b.com", {0, npos, npos}, 0 }, + "mailto://a@b.com", {0, npos, npos}, 0, "mailto://b.com" }, { "http://a%20b/x%20y", false, "http://a%20b/x y", {0, npos, npos}, 0 }, #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) @@ -1200,7 +1230,7 @@ "view-source:x%20y/a b", {0, npos, npos}, 0 }, { "view-source:http://x%20y/a%20b", false, "view-source:http://x%20y/a b", {0, npos, npos}, 0 }, - // clang-format on + // clang-format on }; for (size_t i = 0; i < std::size(test_cases); ++i) { SCOPED_TRACE(testing::Message() << "Index " << i << " input: " @@ -1214,7 +1244,15 @@ AutocompleteMatch match(VerbatimMatchForInput( provider_.get(), client_.get(), input, input.canonicalized_url(), test_cases[i].trim_http)); - EXPECT_EQ(ASCIIToUTF16(test_cases[i].contents), match.contents); + if (use_standard_compliant_non_special_scheme_url_parsing_ && + test_cases[i].contents_when_non_special_url_feature_is_enabled) { + EXPECT_EQ( + ASCIIToUTF16( + test_cases[i].contents_when_non_special_url_feature_is_enabled), + match.contents); + } else { + EXPECT_EQ(ASCIIToUTF16(test_cases[i].contents), match.contents); + } for (size_t match_index = 0; match_index < match.contents_class.size(); ++match_index) { EXPECT_EQ(test_cases[i].offsets[match_index], @@ -1228,6 +1266,8 @@ } } +INSTANTIATE_TEST_SUITE_P(All, HistoryURLProviderParamTest, ::testing::Bool()); + TEST_F(HistoryURLProviderTest, HUPScoringExperiment) { HUPScoringParams max_2000_no_time_decay; max_2000_no_time_decay.typed_count_buckets.buckets().push_back(
diff --git a/components/optimization_guide/core/model_quality/feature_type_map.h b/components/optimization_guide/core/model_quality/feature_type_map.h index fdaacea..933c802 100644 --- a/components/optimization_guide/core/model_quality/feature_type_map.h +++ b/components/optimization_guide/core/model_quality/feature_type_map.h
@@ -7,6 +7,7 @@ #include "components/optimization_guide/proto/features/compose.pb.h" #include "components/optimization_guide/proto/features/default.pb.h" +#include "components/optimization_guide/proto/features/history_query.pb.h" #include "components/optimization_guide/proto/features/tab_organization.pb.h" #include "components/optimization_guide/proto/features/wallpaper_search.pb.h" #include "components/optimization_guide/proto/model_execution.pb.h" @@ -70,6 +71,20 @@ static std::string_view ToString() { return "WallpaperSearch"; } }; +class HistoryQueryFeatureTypeMap { + public: + using LoggingData = proto::HistoryQueryLoggingData; + using Request = proto::HistoryQueryRequest; + using Response = proto::HistoryQueryResponse; + using Quality = proto::HistoryQueryQuality; + + static LoggingData* GetLoggingData(proto::LogAiDataRequest& ai_data_request) { + return ai_data_request.mutable_history_query(); + } + + static std::string_view ToString() { return "HistoryQuery"; } +}; + } // namespace optimization_guide #endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_QUALITY_FEATURE_TYPE_MAP_H_
diff --git a/components/optimization_guide/core/model_quality/model_quality_util.cc b/components/optimization_guide/core/model_quality/model_quality_util.cc index 209a14c..7b3bacf2 100644 --- a/components/optimization_guide/core/model_quality/model_quality_util.cc +++ b/components/optimization_guide/core/model_quality/model_quality_util.cc
@@ -16,6 +16,9 @@ switch (feature) { case proto::LogAiDataRequest::FeatureCase::kCompose: return UserVisibleFeatureKey::kCompose; + case proto::LogAiDataRequest::FeatureCase::kHistoryQuery: // Not implemented yet. + // TODO(b/335659433): Add a UserVisibleFeatureKey for HistoryQuery. + return std::nullopt; case proto::LogAiDataRequest::FeatureCase::kTabOrganization: return UserVisibleFeatureKey::kTabOrganization; case proto::LogAiDataRequest::FeatureCase::kWallpaperSearch:
diff --git a/components/optimization_guide/proto/model_quality_service.proto b/components/optimization_guide/proto/model_quality_service.proto index 8b13ff2..f7a4fe5 100644 --- a/components/optimization_guide/proto/model_quality_service.proto +++ b/components/optimization_guide/proto/model_quality_service.proto
@@ -14,6 +14,7 @@ import "components/optimization_guide/proto/model_quality_metadata.proto"; import "components/optimization_guide/proto/features/default.proto"; import "components/optimization_guide/proto/features/compose.proto"; +import "components/optimization_guide/proto/features/history_query.proto"; import "components/optimization_guide/proto/features/tab_organization.proto"; import "components/optimization_guide/proto/features/wallpaper_search.proto"; @@ -34,6 +35,8 @@ WallpaperSearchLoggingData wallpaper_search = 5; + HistoryQueryLoggingData history_query = 7; + DefaultLoggingData default = 1000; } }
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index f89c6e7d..9d0fef7b 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -995,12 +995,6 @@ identity_status_description_android_ += bullet; identity_status_description_android_ += error.short_description(); } - - if (visible_security_state.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) { - identity_status_description_android_ += u"\n\n"; - identity_status_description_android_ += - l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME); - } #endif }
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp index ea18fa5..40cb4fb 100644 --- a/components/page_info_strings.grdp +++ b/components/page_info_strings.grdp
@@ -180,9 +180,6 @@ <message name="IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD" desc="This message gives details of the cryptographic primitives used to protect the HTTPS connection. It should be translated in a similar manner as IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS"> The connection is encrypted and authenticated using <ph name="CIPHER">$1<ex>AES_128_GCM</ex></ph> and uses <ph name="KX">$2<ex>RSA</ex></ph> as the key exchange mechanism. </message> - <message name="IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME" desc="The text of the identity section when the host is not unique (such as with Intranet host names)."> - The identity of the server you are connected to cannot be fully validated. You are connected to a server using a name only valid within your network, which an external certificate authority has no way to validate ownership of. As some certificate authorities will issue certificates for these names regardless, there is no way to ensure you are connected to the intended website and not an attacker. - </message> <message name="IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT" desc="The text of the connection section when the connection is not encrypted."> Your connection to <ph name="DOMAIN">$1<ex>www.google.com</ex></ph> is not encrypted. </message>
diff --git a/components/password_manager/core/browser/form_parsing/form_data_parser.cc b/components/password_manager/core/browser/form_parsing/form_data_parser.cc index a556478..343e5ed 100644 --- a/components/password_manager/core/browser/form_parsing/form_data_parser.cc +++ b/components/password_manager/core/browser/form_parsing/form_data_parser.cc
@@ -123,8 +123,8 @@ // autocomplete attribute or keywords in field's id and name. bool IsCreditCardField(const ProcessedField& field) { return field.autocomplete_flag == AutocompleteFlag::kCreditCardField || - StringMatchesCVC(field.field->name_attribute) || - StringMatchesCVC(field.field->id_attribute); + StringMatchesCVC(field.field->name_attribute()) || + StringMatchesCVC(field.field->id_attribute()); } // Returns true if the `field` is suspected to be not a password field @@ -135,12 +135,12 @@ bool* otp_field_detected_with_regex = nullptr) { if (IsCreditCardField(field) || field.autocomplete_flag == AutocompleteFlag::kOneTimeCode || - StringMatchesSSN(field.field->name_attribute) || - StringMatchesSSN(field.field->id_attribute)) { + StringMatchesSSN(field.field->name_attribute()) || + StringMatchesSSN(field.field->id_attribute())) { return true; } - bool is_otp_field = StringMatchesOTP(field.field->name_attribute) || - StringMatchesOTP(field.field->id_attribute); + bool is_otp_field = StringMatchesOTP(field.field->name_attribute()) || + StringMatchesOTP(field.field->id_attribute()); if (otp_field_detected_with_regex) { *otp_field_detected_with_regex |= is_otp_field; } @@ -344,7 +344,7 @@ bool CanBeConsideredAsSingleUsernameField(const FormFieldData* field) { return field && util::CanFieldBeConsideredAsSingleUsername( - field->name_attribute, field->id_attribute, field->label()); + field->name_attribute(), field->id_attribute(), field->label()); } // Given a `new_password` field tries to find a matching confirmation_password
diff --git a/components/password_manager/core/browser/form_parsing/form_data_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_data_parser_unittest.cc index 9373fe17c..afd7b842 100644 --- a/components/password_manager/core/browser/form_parsing/form_data_parser_unittest.cc +++ b/components/password_manager/core/browser/form_parsing/form_data_parser_unittest.cc
@@ -294,16 +294,16 @@ const autofill::FieldRendererId renderer_id = GetUniqueId(); field.set_renderer_id(renderer_id); if (field_description.id_attribute == kNonimportantValue) { - field.id_attribute = StampUniqueSuffix(u"html_id"); + field.set_id_attribute(StampUniqueSuffix(u"html_id")); } else { - field.id_attribute = std::u16string(field_description.id_attribute); + field.set_id_attribute(std::u16string(field_description.id_attribute)); } if (field_description.name == kNonimportantValue) { field.set_name(StampUniqueSuffix(u"html_name")); } else { field.set_name(std::u16string(field_description.name)); } - field.name_attribute = field.name(); + field.set_name_attribute(field.name()); field.set_form_control_type(field_description.form_control_type); field.is_focusable = field_description.is_focusable; field.is_enabled = field_description.is_enabled;
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc index 9c9d741..b9554b1f 100644 --- a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc +++ b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc
@@ -43,8 +43,8 @@ result.fields.resize(form_proto.fields_size()); for (int i = 0; i < form_proto.fields_size(); ++i) { const ::form_data_fuzzer::FormField& form_data_proto = form_proto.fields(i); - result.fields[i].id_attribute = UTF8ToUTF16(form_data_proto.id()); - result.fields[i].name_attribute = UTF8ToUTF16(form_data_proto.name()); + result.fields[i].set_id_attribute(UTF8ToUTF16(form_data_proto.id())); + result.fields[i].set_name_attribute(UTF8ToUTF16(form_data_proto.name())); result.fields[i].is_focusable = form_data_proto.is_focusable(); result.fields[i].set_form_control_type( static_cast<autofill::FormControlType>(
diff --git a/components/password_manager/core/browser/form_saver_impl.cc b/components/password_manager/core/browser/form_saver_impl.cc index 658de600..60f6e3b1 100644 --- a/components/password_manager/core/browser/form_saver_impl.cc +++ b/components/password_manager/core/browser/form_saver_impl.cc
@@ -35,8 +35,8 @@ field.options.clear(); field.placeholder = {}; field.css_classes = {}; - field.id_attribute = {}; - field.name_attribute = {}; + field.set_id_attribute({}); + field.set_name_attribute({}); } }
diff --git a/components/password_manager/core/browser/form_saver_impl_unittest.cc b/components/password_manager/core/browser/form_saver_impl_unittest.cc index 3eb7823..6280452c 100644 --- a/components/password_manager/core/browser/form_saver_impl_unittest.cc +++ b/components/password_manager/core/browser/form_saver_impl_unittest.cc
@@ -292,8 +292,8 @@ field.set_value(u"value"); field.set_label(u"label"); field.placeholder = u"placeholder"; - field.id_attribute = u"id"; - field.name_attribute = field.name(); + field.set_id_attribute(u"id"); + field.set_name_attribute(field.name()); field.css_classes = u"css_classes"; pending.form_data.fields.push_back(field); @@ -321,8 +321,8 @@ EXPECT_TRUE(saved_field.value().empty()); EXPECT_TRUE(saved_field.label().empty()); EXPECT_TRUE(saved_field.placeholder.empty()); - EXPECT_TRUE(saved_field.id_attribute.empty()); - EXPECT_TRUE(saved_field.name_attribute.empty()); + EXPECT_TRUE(saved_field.id_attribute().empty()); + EXPECT_TRUE(saved_field.name_attribute().empty()); EXPECT_TRUE(saved_field.css_classes.empty()); }
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index a12fd42..8b1078f 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -405,15 +405,15 @@ FormFieldData field; field.set_name(u"firstname"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(autofill::FieldRendererId(2)); observed_form_.fields.push_back(field); field.set_name(u"username"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(autofill::FieldRendererId(3)); observed_form_.fields.push_back(field); @@ -421,16 +421,16 @@ non_password_form_ = observed_form_; field.set_name(u"password"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(autofill::FieldRendererId(4)); observed_form_.fields.push_back(field); observed_form_only_password_fields_.fields.push_back(field); field.set_name(u"password2"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(autofill::FieldRendererId(5)); observed_form_only_password_fields_.fields.push_back(field); @@ -2136,7 +2136,8 @@ form.fields[kUsernameFieldIndex].renderer_id().value() + 1000)); form.fields[kUsernameFieldIndex].set_name( form.fields[kUsernameFieldIndex].name() + u"1"); - form.fields[kUsernameFieldIndex].id_attribute += u"1"; + form.fields[kUsernameFieldIndex].set_id_attribute( + form.fields[kUsernameFieldIndex].id_attribute() + u"1"); form.fields[kPasswordFieldIndex].set_renderer_id(FieldRendererId( form.fields[kPasswordFieldIndex].renderer_id().value() + 1000));
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index ba1ef06..35a3b28 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -952,13 +952,14 @@ } if (!util::CanFieldBeConsideredAsSingleUsername( - field.name_attribute, field.id_attribute, field.label()) || + field.name_attribute(), field.id_attribute(), field.label()) || !util::CanValueBeConsideredAsSingleUsername(field.value())) { return; } bool is_likely_otp = password_manager::util::IsLikelyOtp( - field.name_attribute, field.id_attribute, field.autocomplete_attribute); + field.name_attribute(), field.id_attribute(), + field.autocomplete_attribute); OnUserModifiedNonPasswordField( driver, field_id, field_value,
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 6b64482..6a1ca93 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -322,8 +322,8 @@ field.options.clear(); field.placeholder = {}; field.css_classes = {}; - field.id_attribute = {}; - field.name_attribute = {}; + field.set_id_attribute({}); + field.set_name_attribute({}); } } @@ -523,16 +523,16 @@ FormFieldData field; field.set_name(u"Email"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"googleuser"); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(FieldRendererId(2)); form_data.fields.push_back(field); field.set_name(u"Passwd"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"p4ssword"); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(FieldRendererId(3)); @@ -606,8 +606,8 @@ FormFieldData field; field.set_name(u"Email"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(FieldRendererId(31)); form_data.fields.push_back(field); @@ -643,7 +643,7 @@ FormFieldData password_field; password_field.set_name(form.password_element); - password_field.id_attribute = form.password_element; + password_field.set_id_attribute(form.password_element); password_field.set_value(form.password_value); password_field.set_form_control_type( autofill::FormControlType::kInputPassword); @@ -652,7 +652,7 @@ FormFieldData captcha_field; captcha_field.set_name(u"captcha_element"); - captcha_field.id_attribute = captcha_field.name(); + captcha_field.set_id_attribute(captcha_field.name()); captcha_field.set_value(u"captcha_value"); captcha_field.set_form_control_type(autofill::FormControlType::kInputText); captcha_field.set_renderer_id(FieldRendererId(3)); @@ -672,8 +672,8 @@ FormFieldData otp_field; otp_field.set_name(form.username_element); - otp_field.name_attribute = form.username_element; - otp_field.id_attribute = form.username_element; + otp_field.set_name_attribute(form.username_element); + otp_field.set_id_attribute(form.username_element); otp_field.set_form_control_type(autofill::FormControlType::kInputText); otp_field.set_renderer_id(FieldRendererId(61)); form.form_data.fields.push_back(otp_field); @@ -689,8 +689,8 @@ FormFieldData search_field; search_field.set_name(u"search_bar"); - search_field.name_attribute = search_field.name(); - search_field.id_attribute = search_field.name_attribute; + search_field.set_name_attribute(search_field.name()); + search_field.set_id_attribute(search_field.name_attribute()); search_field.set_value(u"search_field_value"); search_field.set_form_control_type(autofill::FormControlType::kInputText); @@ -712,7 +712,7 @@ FormFieldData name_field; name_field.set_name(u"name"); - name_field.id_attribute = name_field.name(); + name_field.set_id_attribute(name_field.name()); name_field.set_value(u"Name"); name_field.set_form_control_type(autofill::FormControlType::kInputText); name_field.set_renderer_id(FieldRendererId(2)); @@ -720,7 +720,7 @@ FormFieldData surname_field; surname_field.set_name(form.username_element); - surname_field.id_attribute = surname_field.name(); + surname_field.set_id_attribute(surname_field.name()); surname_field.set_value(form.username_value); surname_field.set_form_control_type(autofill::FormControlType::kInputText); surname_field.set_renderer_id(FieldRendererId(3)); @@ -728,7 +728,7 @@ FormFieldData password_field; password_field.set_name(form.password_element); - password_field.id_attribute = form.password_element; + password_field.set_id_attribute(form.password_element); password_field.set_value(form.password_value); password_field.set_form_control_type( autofill::FormControlType::kInputPassword); @@ -750,7 +750,7 @@ FormFieldData field; field.set_name(form.username_element); - field.id_attribute = field.name(); + field.set_id_attribute(field.name()); field.set_value(form.username_value); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(FieldRendererId(2)); @@ -758,7 +758,7 @@ form.form_data.fields.push_back(field); field.set_name(form.password_element); - field.id_attribute = field.name(); + field.set_id_attribute(field.name()); field.set_value(form.password_value); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(FieldRendererId(3)); @@ -1084,7 +1084,7 @@ ON_CALL(client_, IsSavingAndFillingEnabled(_)).WillByDefault(Return(true)); FormData form_data = MakeSingleUsernameFormData(); - form_data.fields[0].name_attribute = u"onetime"; + form_data.fields[0].set_name_attribute(u"onetime"); FieldRendererId username_renderer_id = form_data.fields[0].renderer_id(); ON_CALL(driver_, GetLastCommittedURL).WillByDefault(ReturnRef(form_data.url)); @@ -1169,8 +1169,8 @@ FormFieldData& field = form_data.fields[0]; field.set_form_control_type(autofill::FormControlType::kInputCheckbox); field.set_name(u"checkbox"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); ON_CALL(driver_, GetLastCommittedURL).WillByDefault(ReturnRef(form_data.url)); @@ -1201,8 +1201,8 @@ FormData form_data = MakeSingleUsernameFormData(); // Single character values that aren't considered as a username. - form_data.fields[0].name_attribute = u"a"; - form_data.fields[0].id_attribute = u"a"; + form_data.fields[0].set_name_attribute(u"a"); + form_data.fields[0].set_id_attribute(u"a"); ON_CALL(driver_, GetLastCommittedURL).WillByDefault(ReturnRef(form_data.url)); @@ -2156,8 +2156,8 @@ ASSERT_FALSE(form_data.fields[1].value().empty()); FormFieldData field; field.set_name(u"new_password_element"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(FieldRendererId(4)); form_data.fields.push_back(field); @@ -3844,7 +3844,7 @@ non_password_form.password_value = u"379 390"; // One time SMS code. non_password_form.form_data.fields[1].set_value( non_password_form.password_value); - non_password_form.form_data.fields[1].id_attribute = u"one-time-code"; + non_password_form.form_data.fields[1].set_id_attribute(u"one-time-code"); non_password_form.only_for_fallback = true; PasswordFormFillData form_data; @@ -3943,7 +3943,7 @@ one_time_code_form.password_element = u"one-time-code"; one_time_code_form.form_data.url = one_time_code_form.url; FormFieldData field; - field.name_attribute = one_time_code_form.password_element; + field.set_name_attribute(one_time_code_form.password_element); field.set_value(one_time_code_form.password_value); field.set_form_control_type(autofill::FormControlType::kInputPassword); one_time_code_form.form_data.fields.push_back(field); @@ -4002,8 +4002,8 @@ one_time_code_form.password_element = u"one-time-code"; one_time_code_form.form_data.fields[1].set_value( one_time_code_form.password_value); - one_time_code_form.form_data.fields[1].name_attribute = - one_time_code_form.password_element; + one_time_code_form.form_data.fields[1].set_name_attribute( + one_time_code_form.password_element); PasswordFormFillData form_data; EXPECT_CALL(driver_, SetPasswordFillData) @@ -4897,7 +4897,7 @@ otp_form.password_element = u"one-time-code"; otp_form.only_for_fallback = true; otp_form.form_data.fields[0].set_name(otp_form.password_element); - otp_form.form_data.fields[0].name_attribute = otp_form.password_element; + otp_form.form_data.fields[0].set_name_attribute(otp_form.password_element); manager()->OnPasswordFormsParsed(&driver_, {otp_form.form_data}); manager()->OnPasswordFormsRendered(&driver_, {otp_form.form_data}); @@ -5760,12 +5760,12 @@ one_time_code_form.form_data.fields.push_back(otp_field); switch (prediction_type) { case PredictionSource::ID_ATTRIBUTE: - one_time_code_form.form_data.fields[otp_form_has_username].id_attribute = - test_form_password_element_; + one_time_code_form.form_data.fields[otp_form_has_username] + .set_id_attribute(test_form_password_element_); break; case PredictionSource::NAME_ATTRIBUTE: one_time_code_form.form_data.fields[otp_form_has_username] - .name_attribute = test_form_password_element_; + .set_name_attribute(test_form_password_element_); break; case PredictionSource::AUTOCOMPLETE: one_time_code_form.form_data.fields[otp_form_has_username]
diff --git a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc index f87a462..a74251d 100644 --- a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
@@ -214,30 +214,30 @@ FormFieldData field; field.set_name(u"firstname"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(autofill::FieldRendererId(1)); observed_form_.fields.push_back(field); field.set_name(u"username"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(autofill::FieldRendererId(2)); observed_form_.fields.push_back(field); field.set_name(u"password"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(autofill::FieldRendererId(3)); observed_form_.fields.push_back(field); observed_form_only_password_fields_.fields.push_back(field); field.set_name(u"password2"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(autofill::FieldRendererId(5)); observed_form_only_password_fields_.fields.push_back(field); @@ -1302,23 +1302,23 @@ const std::u16string matched_form_username_field_name = u"new_username_id"; FormFieldData field1; field1.set_name(matched_form_username_field_name); - field1.id_attribute = field1.name(); - field1.name_attribute = field1.name(); + field1.set_id_attribute(field1.name()); + field1.set_name_attribute(field1.name()); field1.set_form_control_type(autofill::FormControlType::kInputText); saved_match_.form_data.fields.push_back(field1); FormFieldData field2; field2.set_name(u"firstname"); - field2.id_attribute = field2.name(); - field2.name_attribute = field2.name(); + field2.set_id_attribute(field2.name()); + field2.set_name_attribute(field2.name()); field2.set_form_control_type(autofill::FormControlType::kInputText); saved_match_.form_data.fields.push_back(field2); saved_match_.username_element = field2.name(); FormFieldData field3; field3.set_name(u"password"); - field3.id_attribute = field3.name(); - field3.name_attribute = field3.name(); + field3.set_id_attribute(field3.name()); + field3.set_name_attribute(field3.name()); field3.set_form_control_type(autofill::FormControlType::kInputPassword); saved_match_.form_data.fields.push_back(field3); saved_match_.password_element = field3.name();
diff --git a/components/password_manager/ios/shared_password_controller_unittest.mm b/components/password_manager/ios/shared_password_controller_unittest.mm index 32cf85b3..189e93d5 100644 --- a/components/password_manager/ios/shared_password_controller_unittest.mm +++ b/components/password_manager/ios/shared_password_controller_unittest.mm
@@ -612,16 +612,16 @@ autofill::FormFieldData field; field.set_name(u"Username"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"googleuser"); field.set_form_control_type(autofill::FormControlType::kInputText); field.set_renderer_id(autofill::test::MakeFieldRendererId()); form_data.fields.push_back(field); field.set_name(u"Passwd"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"p4ssword"); field.set_form_control_type(autofill::FormControlType::kInputPassword); field.set_renderer_id(autofill::test::MakeFieldRendererId());
diff --git a/components/password_manager/ios/test_helpers.cc b/components/password_manager/ios/test_helpers.cc index f4a24e0..8bfad75 100644 --- a/components/password_manager/ios/test_helpers.cc +++ b/components/password_manager/ios/test_helpers.cc
@@ -96,15 +96,15 @@ autofill::FormFieldData field; field.set_name(u"Username"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"googleuser"); field.set_form_control_type(autofill::FormControlType::kInputText); form_data.fields.push_back(field); field.set_name(u"Passwd"); - field.id_attribute = field.name(); - field.name_attribute = field.name(); + field.set_id_attribute(field.name()); + field.set_name_attribute(field.name()); field.set_value(u"p4ssword"); field.set_form_control_type(autofill::FormControlType::kInputPassword); form_data.fields.push_back(field);
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/BuiltInDnsClientEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/BuiltInDnsClientEnabled.yaml index 422b221f..d915877 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/BuiltInDnsClientEnabled.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/BuiltInDnsClientEnabled.yaml
@@ -3,11 +3,9 @@ desc: |- This policy controls which software stack is used to communicate with the DNS server: the Operating System DNS client, or <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>'s built-in DNS client. This policy does not affect which DNS servers are used: if, for example, the operating system is configured to use an enterprise DNS server, that same server would be used by the built-in DNS client. It also does not control if DNS-over-HTTPS is used; <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will always use the built-in resolver for DNS-over-HTTPS requests. Please see the <ph name="DNS_OVER_HTTPS_MODE_POLICY_NAME">DnsOverHttpsMode</ph> policy for information on controlling DNS-over-HTTPS. - If this policy is set to Enabled, the built-in DNS client will be used, if available. + If this policy is set to Enabled or is left unset, the built-in DNS client will be used. If this policy is set to Disabled, the built-in DNS client will only be used when DNS-over-HTTPS is in use. - - If this policy is left unset, the built-in DNS client will be enabled by default on <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, <ph name="MAC_OS_NAME">macOS</ph>, <ph name="ANDROID_NAME">Android</ph> (when neither Private DNS nor VPN are enabled) and <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph>. example_value: true features: dynamic_refresh: true @@ -15,11 +13,11 @@ future_on: - fuchsia items: -- caption: Always use the built-in DNS client if available +- caption: Always use the built-in DNS client value: true - caption: Never use the built-in DNS client value: false -- caption: Use the built-in DNS client on Windows, macOS, Android and ChromeOS +- caption: Always use the built-in DNS client value: null owners: - ericorth@chromium.org
diff --git a/components/power_metrics/energy_metrics_provider_win.h b/components/power_metrics/energy_metrics_provider_win.h index dacf9f4..1619f09 100644 --- a/components/power_metrics/energy_metrics_provider_win.h +++ b/components/power_metrics/energy_metrics_provider_win.h
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include <vector> #include "base/win/scoped_handle.h" #include "components/power_metrics/energy_metrics_provider.h"
diff --git a/components/prefs/android/pref_service_android.cc b/components/prefs/android/pref_service_android.cc index 2c2b248..1ec2e85 100644 --- a/components/prefs/android/pref_service_android.cc +++ b/components/prefs/android/pref_service_android.cc
@@ -18,7 +18,7 @@ namespace jni_zero { template <> -COMPONENTS_PREFS_EXPORT PrefService* FromJniType<PrefService*, jobject>( +COMPONENTS_PREFS_EXPORT PrefService* FromJniType<PrefService*>( JNIEnv* env, const JavaRef<jobject>& obj) { return PrefServiceAndroid::FromPrefServiceAndroid(obj);
diff --git a/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java b/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java index 6d6d8b21..37ca13f 100644 --- a/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java +++ b/components/search_engines/android/java/src/org/chromium/components/search_engines/TemplateUrl.java
@@ -6,6 +6,8 @@ import org.jni_zero.CalledByNative; import org.jni_zero.NativeMethods; +import org.chromium.build.annotations.MockedInTests; + import java.util.Locale; /** @@ -13,6 +15,7 @@ * from native side. Any class uses this need to register a {@link TemplateUrlServiceObserver} on * {@link TemplatUrlService} to listen the native changes in case the native pointer is destroyed. */ +@MockedInTests public class TemplateUrl { private final long mTemplateUrlPtr;
diff --git a/components/search_provider_logos/google_logo_api_unittest.cc b/components/search_provider_logos/google_logo_api_unittest.cc index e57385f..53b299c 100644 --- a/components/search_provider_logos/google_logo_api_unittest.cc +++ b/components/search_provider_logos/google_logo_api_unittest.cc
@@ -181,8 +181,8 @@ ASSERT_FALSE(failed); ASSERT_TRUE(logo); - EXPECT_EQ("abc", logo->encoded_image->data()); - EXPECT_EQ("xyz", logo->dark_encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); + EXPECT_EQ("xyz", logo->dark_encoded_image->as_string()); EXPECT_EQ(LogoType::SIMPLE, logo->metadata.type); } @@ -218,7 +218,7 @@ ASSERT_FALSE(failed); ASSERT_TRUE(logo); - EXPECT_EQ("abc", logo->encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); EXPECT_EQ(LogoType::SIMPLE, logo->metadata.type); EXPECT_EQ("https://g.co/", logo->metadata.short_link); @@ -266,7 +266,7 @@ ASSERT_FALSE(failed); ASSERT_TRUE(logo); - EXPECT_EQ("abc", logo->encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); EXPECT_EQ(LogoType::SIMPLE, logo->metadata.type); ASSERT_TRUE(logo->metadata.short_link.is_empty()); ASSERT_TRUE(logo->metadata.share_button_icon.empty()); @@ -311,7 +311,7 @@ ASSERT_FALSE(failed); ASSERT_TRUE(logo); - EXPECT_EQ("abc", logo->encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); EXPECT_EQ(LogoType::SIMPLE, logo->metadata.type); ASSERT_FALSE(logo->metadata.short_link.is_valid()); ASSERT_TRUE(logo->metadata.share_button_icon.empty()); @@ -363,7 +363,7 @@ ASSERT_TRUE(logo); EXPECT_EQ(GURL("https://www.doodle.com/image.gif"), logo->metadata.animated_url); - EXPECT_EQ("abc", logo->encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); EXPECT_EQ(LogoType::ANIMATED, logo->metadata.type); EXPECT_EQ("https://g.co/", logo->metadata.short_link); @@ -413,8 +413,8 @@ EXPECT_EQ(GURL("https://www.doodle.com/dark_image.gif"), logo->metadata.dark_animated_url); EXPECT_EQ("#ABCDEF", logo->metadata.dark_background_color); - EXPECT_EQ("abc", logo->encoded_image->data()); - EXPECT_EQ("xyz", logo->dark_encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); + EXPECT_EQ("xyz", logo->dark_encoded_image->as_string()); EXPECT_EQ(LogoType::ANIMATED, logo->metadata.type); } @@ -529,7 +529,7 @@ EXPECT_EQ(GURL("https://base.doo/play"), logo->metadata.full_page_url); EXPECT_EQ(0, logo->metadata.iframe_width_px); EXPECT_EQ(0, logo->metadata.iframe_height_px); - EXPECT_EQ("abc", logo->encoded_image->data()); + EXPECT_EQ("abc", logo->encoded_image->as_string()); } TEST(GoogleNewLogoApiTest, DefaultsInteractiveIframeSize) {
diff --git a/components/search_provider_logos/logo_cache.cc b/components/search_provider_logos/logo_cache.cc index 6603a2a..a7d8404 100644 --- a/components/search_provider_logos/logo_cache.cc +++ b/components/search_provider_logos/logo_cache.cc
@@ -170,7 +170,7 @@ if (logo_num_bytes_ != 0) { encoded_image = new base::RefCountedString(); - if (!base::ReadFileToString(logo_path, &encoded_image->data())) { + if (!base::ReadFileToString(logo_path, &encoded_image->as_string())) { UpdateMetadata(nullptr); return nullptr; } @@ -187,7 +187,8 @@ if (dark_logo_num_bytes_ != 0) { dark_encoded_image = new base::RefCountedString(); - if (!base::ReadFileToString(dark_logo_path, &dark_encoded_image->data())) { + if (!base::ReadFileToString(dark_logo_path, + &dark_encoded_image->as_string())) { UpdateMetadata(nullptr); return nullptr; }
diff --git a/components/search_provider_logos/logo_cache_unittest.cc b/components/search_provider_logos/logo_cache_unittest.cc index 21a74670..976e338 100644 --- a/components/search_provider_logos/logo_cache_unittest.cc +++ b/components/search_provider_logos/logo_cache_unittest.cc
@@ -76,7 +76,7 @@ base::RefCountedString* CreateExampleImage(size_t num_bytes) { base::RefCountedString* encoded_image_str = new base::RefCountedString(); - std::string& str = encoded_image_str->data(); + std::string& str = encoded_image_str->as_string(); str.resize(num_bytes); for (size_t i = 0; i < num_bytes; ++i) str[i] = static_cast<char>(i);
diff --git a/components/search_provider_logos/logo_service_impl.cc b/components/search_provider_logos/logo_service_impl.cc index 4ff10ad..c172e7e3 100644 --- a/components/search_provider_logos/logo_service_impl.cc +++ b/components/search_provider_logos/logo_service_impl.cc
@@ -397,7 +397,7 @@ scoped_refptr<base::RefCountedString> encoded_image = cached_logo->encoded_image; image_decoder_->DecodeImage( - encoded_image->data(), gfx::Size(), // No particular size desired. + encoded_image->as_string(), gfx::Size(), // No particular size desired. /*data_decoder=*/nullptr, ImageDecodedHandlerWithTimeout::Wrap(base::BindOnce( &LogoServiceImpl::OnLightCachedImageDecoded, @@ -437,7 +437,8 @@ cached_logo->dark_encoded_image; image_decoder_->DecodeImage( - dark_encoded_image->data(), gfx::Size(), // No particular size desired. + dark_encoded_image->as_string(), + gfx::Size(), // No particular size desired. /*data_decoder=*/nullptr, ImageDecodedHandlerWithTimeout::Wrap(base::BindOnce( &LogoServiceImpl::OnCachedLogoAvailable, @@ -532,7 +533,7 @@ scoped_refptr<base::RefCountedString> encoded_image = logo->encoded_image; image_decoder_->DecodeImage( - encoded_image->data(), gfx::Size(), // No particular size desired. + encoded_image->as_string(), gfx::Size(), // No particular size desired. /*data_decoder=*/nullptr, ImageDecodedHandlerWithTimeout::Wrap(base::BindOnce( &LogoServiceImpl::OnLightFreshImageDecoded, @@ -560,7 +561,8 @@ logo->dark_encoded_image; image_decoder_->DecodeImage( - dark_encoded_image->data(), gfx::Size(), // No particular size desired. + dark_encoded_image->as_string(), + gfx::Size(), // No particular size desired. /*data_decoder=*/nullptr, ImageDecodedHandlerWithTimeout::Wrap(base::BindOnce( &LogoServiceImpl::OnFreshLogoAvailable,
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc index acede1c3..be68a5fa 100644 --- a/components/search_provider_logos/logo_service_impl_unittest.cc +++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -77,14 +77,13 @@ const SkBitmap& bitmap) { scoped_refptr<base::RefCountedMemory> png_bytes = gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes(); - scoped_refptr<base::RefCountedString> str = new base::RefCountedString(); - str->data().assign(png_bytes->front_as<char>(), png_bytes->size()); - return str; + return base::MakeRefCounted<base::RefCountedString>( + std::string(base::as_string_view(*png_bytes))); } std::string EncodeBitmapAsPNGBase64(const SkBitmap& bitmap) { scoped_refptr<base::RefCountedString> png_bytes = EncodeBitmapAsPNG(bitmap); - return base::Base64Encode(png_bytes->data()); + return base::Base64Encode(*png_bytes); } SkBitmap MakeBitmap(int width, int height) {
diff --git a/components/security_interstitials/core/ssl_error_options_mask.cc b/components/security_interstitials/core/ssl_error_options_mask.cc index 0c0c034..1d15480 100644 --- a/components/security_interstitials/core/ssl_error_options_mask.cc +++ b/components/security_interstitials/core/ssl_error_options_mask.cc
@@ -19,6 +19,7 @@ case net::ERR_CERT_NO_REVOCATION_MECHANISM: case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM: + case net::ERR_CERT_NON_UNIQUE_NAME: case net::ERR_CERT_WEAK_KEY: case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION: case net::ERR_CERT_VALIDITY_TOO_LONG:
diff --git a/components/segmentation_platform/public/android/input_context_android.cc b/components/segmentation_platform/public/android/input_context_android.cc index 5951b45..d0279f4 100644 --- a/components/segmentation_platform/public/android/input_context_android.cc +++ b/components/segmentation_platform/public/android/input_context_android.cc
@@ -63,8 +63,7 @@ JNIEnv* env, const base::android::JavaRef<jobjectArray>& j_gurls, std::vector<GURL>* ret) { - *ret = jni_zero::ConvertArray<std::vector<GURL>>::FromJniType<jobject>( - env, j_gurls); + *ret = jni_zero::ConvertArray<std::vector<GURL>>::FromJniType(env, j_gurls); } static void JavaLongArrayToBaseTimeVector(
diff --git a/components/sessions/core/live_tab_context.h b/components/sessions/core/live_tab_context.h index a8ac85d5..4cb7299 100644 --- a/components/sessions/core/live_tab_context.h +++ b/components/sessions/core/live_tab_context.h
@@ -30,7 +30,6 @@ namespace sessions { class LiveTab; -class SerializedNavigationEntry; // An interface representing the context in which LiveTab instances exist in the // embedder. As a concrete example, desktop Chrome has an implementation that @@ -68,36 +67,19 @@ virtual ui::WindowShowState GetRestoredState() const = 0; virtual std::string GetWorkspace() const = 0; - // Note: |tab_platform_data| may be null (e.g., if restoring from last session + // Note: |tab.platform_data| may be null (e.g., if restoring from last session // as this data is not persisted, or if the platform does not provide // platform-specific data). - // |tab_id| is the tab's unique SessionID. Only present if a historical tab + // |tab.id| is the tab's unique SessionID. Only present if a historical tab // has been created by TabRestoreService. - virtual LiveTab* AddRestoredTab( - const std::vector<SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) = 0; + virtual LiveTab* AddRestoredTab(const tab_restore::Tab& tab, + int tab_index, + bool select) = 0; - // Note: |tab_platform_data| may be null (e.g., if restoring from last session + // Note: |tab.platform_data| may be null (e.g., if restoring from last session // as this data is not persisted, or if the platform does not provide // platform-specific data). - virtual LiveTab* ReplaceRestoredTab( - const std::vector<SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) = 0; + virtual LiveTab* ReplaceRestoredTab(const tab_restore::Tab& tab) = 0; virtual void CloseTab() = 0; protected:
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc index 3ac30d5..110346c 100644 --- a/components/sessions/core/tab_restore_service_helper.cc +++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -518,7 +518,7 @@ new_group_ids; for (size_t tab_i = 0; tab_i < window.tabs.size(); ++tab_i) { - const Tab& tab = *window.tabs[tab_i]; + Tab& tab = *window.tabs[tab_i]; // Relabel group IDs to prevent duplicating groups, e.g. if the same // window is restored twice or a tab of the same ID is restored @@ -538,15 +538,13 @@ } new_group = it->second; + tab.group = new_group; } LiveTab* restored_tab = context->AddRestoredTab( - tab.navigations, context->GetTabCount(), - tab.current_navigation_index, tab.extension_app_id, new_group, - tab.group_visual_data.value_or(tab_groups::TabGroupVisualData()), - static_cast<int>(tab_i) == window.selected_tab_index, tab.pinned, - tab.platform_data.get(), tab.user_agent_override, tab.extra_data, - nullptr); + tab, /*tab_index=*/context->GetTabCount(), + /*select=*/static_cast<int>(tab_i) == window.selected_tab_index); + if (restored_tab) { client_->OnTabRestored( tab.navigations.at(tab.current_navigation_index).virtual_url()); @@ -886,23 +884,19 @@ LiveTab** live_tab) { LiveTab* restored_tab; if (disposition == WindowOpenDisposition::CURRENT_TAB && context) { - restored_tab = context->ReplaceRestoredTab( - tab.navigations, std::nullopt, tab.current_navigation_index, - tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override, - tab.extra_data); + restored_tab = context->ReplaceRestoredTab(tab); } else { // We only respect the tab's original browser if there's no disposition. - if (disposition == WindowOpenDisposition::UNKNOWN) { - if (tab.browser_id) { - context = client_->FindLiveTabContextWithID( - SessionID::FromSerializedValue(tab.browser_id)); - } + if (disposition == WindowOpenDisposition::UNKNOWN && tab.browser_id) { + context = client_->FindLiveTabContextWithID( + SessionID::FromSerializedValue(tab.browser_id)); } // Restore a grouped tab into its original group, even if the group has // since been moved to a different context. If the original group doesn't // exist any more, fall back to using the tab's original browser. if (tab.group.has_value()) { + // TODO: This needs to look at the saved id. LiveTabContext* group_context = client_->FindLiveTabContextWithGroup(tab.group.value()); if (group_context) { @@ -935,12 +929,8 @@ } restored_tab = context->AddRestoredTab( - tab.navigations, tab_index, tab.current_navigation_index, - tab.extension_app_id, tab.group, - tab.group_visual_data.value_or(tab_groups::TabGroupVisualData()), - disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB, tab.pinned, - tab.platform_data.get(), tab.user_agent_override, tab.extra_data, - &tab.id); + tab, tab_index, + /*select=*/disposition != WindowOpenDisposition::NEW_BACKGROUND_TAB); } client_->OnTabRestored(
diff --git a/components/ssl_errors/error_info.cc b/components/ssl_errors/error_info.cc index ef1471e..f14ab0d 100644 --- a/components/ssl_errors/error_info.cc +++ b/components/ssl_errors/error_info.cc
@@ -176,6 +176,13 @@ short_description = l10n_util::GetStringUTF16( IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DESCRIPTION); break; + case CERT_NON_UNIQUE_NAME: + details = + l10n_util::GetStringFUTF16(IDS_CERT_ERROR_NON_UNIQUE_NAME_DETAILS, + UTF8ToUTF16(request_url.host())); + short_description = + l10n_util::GetStringUTF16(IDS_CERT_ERROR_NON_UNIQUE_NAME_DESCRIPTION); + break; case UNKNOWN: details = l10n_util::GetStringUTF16(IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS); short_description = @@ -210,6 +217,8 @@ return CERT_INVALID; case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM: return CERT_WEAK_SIGNATURE_ALGORITHM; + case net::ERR_CERT_NON_UNIQUE_NAME: + return CERT_NON_UNIQUE_NAME; case net::ERR_CERT_WEAK_KEY: return CERT_WEAK_KEY; case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION: @@ -245,6 +254,7 @@ net::CERT_STATUS_REVOKED, net::CERT_STATUS_INVALID, net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, + net::CERT_STATUS_NON_UNIQUE_NAME, net::CERT_STATUS_WEAK_KEY, net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION, net::CERT_STATUS_VALIDITY_TOO_LONG, @@ -262,6 +272,7 @@ CERT_REVOKED, CERT_INVALID, CERT_WEAK_SIGNATURE_ALGORITHM, + CERT_NON_UNIQUE_NAME, CERT_WEAK_KEY, CERT_NAME_CONSTRAINT_VIOLATION, CERT_VALIDITY_TOO_LONG,
diff --git a/components/ssl_errors/error_info.h b/components/ssl_errors/error_info.h index 35a094e..797cf32 100644 --- a/components/ssl_errors/error_info.h +++ b/components/ssl_errors/error_info.h
@@ -42,6 +42,7 @@ CERT_SYMANTEC_LEGACY = 16, CERT_KNOWN_INTERCEPTION_BLOCKED = 17, LEGACY_TLS = 18, + CERT_NON_UNIQUE_NAME = 19, END_OF_ENUM };
diff --git a/components/ssl_errors_strings.grdp b/components/ssl_errors_strings.grdp index 2336760..33e54d9 100644 --- a/components/ssl_errors_strings.grdp +++ b/components/ssl_errors_strings.grdp
@@ -102,6 +102,13 @@ The server certificate has a validity period that is too long. </message> + <message name="IDS_CERT_ERROR_NON_UNIQUE_NAME_DETAILS" desc="Details of the error page for a certificate for a non-unique name"> + You attempted to reach <ph name="DOMAIN"><strong>$1<ex>paypal.com</ex></strong></ph>, but the server presented an invalid certificate issued to that name. The name is a reserved IP address or internal hostname. + </message> + <message name="IDS_CERT_ERROR_NON_UNIQUE_NAME_DESCRIPTION" desc="Description of the error page for a certificate for a non-unique name"> + The server certificate is issued to a non-unique name. + </message> + <message name="IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS" desc="Details of the error page for an unknown ssl error"> An unknown error has occurred. </message>
diff --git a/components/ssl_errors_strings_grdp/IDS_CERT_ERROR_NON_UNIQUE_NAME_DETAILS.png.sha1 b/components/ssl_errors_strings_grdp/IDS_CERT_ERROR_NON_UNIQUE_NAME_DETAILS.png.sha1 new file mode 100644 index 0000000..99aa07e --- /dev/null +++ b/components/ssl_errors_strings_grdp/IDS_CERT_ERROR_NON_UNIQUE_NAME_DETAILS.png.sha1
@@ -0,0 +1 @@ +bc00fb1724ad77ee9f8c79a411881facb60fc4eb \ No newline at end of file
diff --git a/components/sync_bookmarks/bookmark_specifics_conversions.cc b/components/sync_bookmarks/bookmark_specifics_conversions.cc index 21e75b2..62fe453 100644 --- a/components/sync_bookmarks/bookmark_specifics_conversions.cc +++ b/components/sync_bookmarks/bookmark_specifics_conversions.cc
@@ -110,9 +110,8 @@ bookmark_node->GetTitle()); const std::string& icon_bytes_str = specifics.favicon(); - scoped_refptr<base::RefCountedString> icon_bytes( - new base::RefCountedString()); - icon_bytes->data().assign(icon_bytes_str); + auto icon_bytes = base::MakeRefCounted<base::RefCountedString>(); + icon_bytes->as_string().assign(icon_bytes_str); GURL icon_url(specifics.icon_url()); @@ -325,7 +324,7 @@ } if (favicon_bytes.get() && favicon_bytes->size() != 0) { - bm_specifics->set_favicon(favicon_bytes->front(), favicon_bytes->size()); + bm_specifics->set_favicon(favicon_bytes->data(), favicon_bytes->size()); // Avoid sync-ing favicon URLs that are unreasonably large, as determined by // |kMaxFaviconUrlSize|. Most notably, URLs prefixed with the data: scheme // to embed the content of the image itself in the URL may be arbitrarily
diff --git a/components/test/data/media_router/common/providers/cast/certificate/certificates/generated_root_cast_receiver.pem b/components/test/data/media_router/common/providers/cast/certificate/certificates/generated_root_cast_receiver.pem new file mode 100644 index 0000000..783bd91 --- /dev/null +++ b/components/test/data/media_router/common/providers/cast/certificate/certificates/generated_root_cast_receiver.pem
@@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyTCCAbGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxDYXN0 +IFJvb3QgQ0EwHhcNMjQwNDAyMTg0MjA3WhcNMjQwNDA1MTg0MjA3WjAXMRUwEwYD +VQQDDAxDYXN0IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCY8saMRTmNFNB5DPYyXAnUA6IEspfqIOI92+K93NlSUPFyE4xjPpr7xduKhQ69 +JgzTgXUMrVpAst3L02YVjWhHuAJhVhnkxqVsidXkULkSGXQmxhxQuLLRMQEFlGZW +Zhezvh5029pNG27dCwLdORdr1G5oqyIoBDJD8aJ2rCbO+4Jd2hMJwymicgvNgJKh +5bZU/Qnstcqi9pjXWGrQH6KfGwoaZ0EyddodTRfHIN0mxIKjOibEHzESyXDeSvhp +Shxd69eO7kZagtIOzvTOUo9SI86cR90566UF/lX4cit8vUfGsdOUemyqYT42KR3D +n/fE/5tF42Ih/vOPaVDxTaaRAgMBAAGjIDAeMAsGA1UdDwQEAwIChDAPBgNVHRMB +Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBJEKT1mX8U07Flxo3AaSIgZGU5 +yDjxORV5Xcd4V3zTr/0Geqt9BIhLfyOrJmkYqN7ZS5kCJbu6k16+g2RmxIsIRqi4 +hFHZrja0SLWxnJCmYnoViWqfVS7Oq7R72xUw3JENa6UZ0/iGqpA5VLndaTvHzDHT +66hqB84o/xH2NybaYFglpaC4NXWzvxjo8d2JmiJYJXmilqU1fCXT42rslz+bMUy/ +pWGunKvExto+kUAkXaB07pF1EfLapIGSzoLYi4+2gZ9RW4VpMPGXbgZe2Uj+CMTS +g3p0Hr1fPkZ4Vp3fMMxU29eBB6Ysnh5zLh2QaTDcf2TrqVEobSv8CyFpU2CF +-----END CERTIFICATE-----
diff --git a/components/tpcd/metadata/manager.cc b/components/tpcd/metadata/manager.cc index b6007b2..5c89729f 100644 --- a/components/tpcd/metadata/manager.cc +++ b/components/tpcd/metadata/manager.cc
@@ -5,6 +5,7 @@ #include "components/tpcd/metadata/manager.h" #include <cstdint> +#include <memory> #include <random> #include <string> #include <utility> @@ -23,6 +24,7 @@ #include "components/content_settings/core/common/content_settings_utils.h" #include "components/content_settings/core/common/features.h" #include "components/content_settings/core/common/host_indexed_content_settings.h" +#include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/tpcd/metadata/metadata.pb.h" #include "components/tpcd/metadata/parser.h" @@ -55,6 +57,8 @@ local_state_(local_state) { CHECK(parser_); + rand_generator_ = std::make_unique<RandGenerator>(); + if (base::FeatureList::IsEnabled( content_settings::features::kHostIndexedMetadataGrants)) { base::AutoLock lock(grants_lock_); @@ -74,15 +78,7 @@ parser_->RemoveObserver(this); } -bool Manager::IsAllowed(const GURL& url, - const GURL& first_party_url, - content_settings::SettingInfo* out_info) const { - base::AutoLock lock(grants_lock_); - return CONTENT_SETTING_ALLOW == - GetContentSetting(grants_, url, first_party_url, out_info); -} - -uint32_t Manager::GenerateRand() const { +uint32_t Manager::RandGenerator::Generate() const { base::RandomBitGenerator generator; std::uniform_int_distribution<uint32_t> distribution(Parser::kMinDtrp + 1, Parser::kMaxDtrp); @@ -90,16 +86,12 @@ return rand; } -std::string Manager::GenerateKeyHash( - const MetadataEntry& metadata_entry) const { - std::string key = base::StrCat( - {metadata_entry.primary_pattern_spec(), - /*Non-url delimiter:*/ "\\", metadata_entry.secondary_pattern_spec(), - base::NumberToString(ElectedDtrp(metadata_entry))}); - - // The hash from SHA1 is faster to obtain than SHA256 and will be forever - // unchanged if key is unchanged and provides lesser collision risk than MD5. - return base::Base64Encode(base::SHA1HashString(key)); +bool Manager::IsAllowed(const GURL& url, + const GURL& first_party_url, + content_settings::SettingInfo* out_info) const { + base::AutoLock lock(grants_lock_); + return CONTENT_SETTING_ALLOW == + GetContentSetting(grants_, url, first_party_url, out_info); } void Manager::SetGrants(const ContentSettingsForOneType& grants) { @@ -124,11 +116,8 @@ } } -void Manager::OnMetadataReady() { - if (!base::FeatureList::IsEnabled(net::features::kTpcdMetadataGrants)) { - return; - } - +ContentSettingsForOneType Manager::BuildGrantsWithPredicate( + base::FunctionRef<bool(const MetadataEntry&)> predicate) { base::flat_set<std::string> remove_keys; if (base::FeatureList::IsEnabled( net::features::kTpcdMetadataStagedRollback) && @@ -168,10 +157,10 @@ cohort = content_settings::mojom::TpcdMetadataCohort::DEFAULT; } - std::string key_hash = GenerateKeyHash(metadata_entry); + std::string key_hash = helpers::GenerateKeyHash(metadata_entry); // Get the cohort from the prefs if available. - if (!cohort.has_value()) { + if (!cohort.has_value() && !predicate(metadata_entry)) { if (local_state_) { const base::Value::Dict& dict = local_state_->GetDict(prefs::kCohorts); @@ -190,7 +179,7 @@ } if (!cohort.has_value()) { - cohort = GenerateRand() <= ElectedDtrp(metadata_entry) + cohort = rand_generator_->Generate() <= ElectedDtrp(metadata_entry) ? content_settings::mojom::TpcdMetadataCohort:: GRACE_PERIOD_FORCED_OFF : content_settings::mojom::TpcdMetadataCohort:: @@ -199,6 +188,10 @@ if (local_state_) { ScopedDictPrefUpdate update(local_state_, prefs::kCohorts); update->Set(key_hash, static_cast<int32_t>(cohort.value())); + + if (predicate(metadata_entry)) { + remove_keys.erase(key_hash); + } } } @@ -219,11 +212,19 @@ } } - SetGrants(grants); + return grants; +} + +void Manager::OnMetadataReady() { + if (!base::FeatureList::IsEnabled(net::features::kTpcdMetadataGrants)) { + return; + } + + SetGrants( + BuildGrantsWithPredicate([](const MetadataEntry&) { return false; })); } ContentSettingsForOneType Manager::GetGrants() const { - if (!base::FeatureList::IsEnabled(net::features::kTpcdMetadataGrants)) { return ContentSettingsForOneType(); } @@ -239,4 +240,45 @@ return absl::get<ContentSettingsForOneType>(grants_); } +void Manager::ResetCohorts(PatternSourcePredicate pattern_predicate) { + if (!base::FeatureList::IsEnabled( + net::features::kTpcdMetadataStagedRollback)) { + return; + } + + if (pattern_predicate.is_null()) { + SetGrants( + BuildGrantsWithPredicate([](const MetadataEntry&) { return true; })); + return; + } + + auto reset_cohort = [&](const MetadataEntry& metadata_entry) -> bool { + if (!Parser::IsDtrpEligible( + Parser::ToRuleSource(metadata_entry.source()))) { + return false; + } + + const auto primary_pattern = ContentSettingsPattern::FromString( + metadata_entry.primary_pattern_spec()); + const auto secondary_pattern = ContentSettingsPattern::FromString( + metadata_entry.secondary_pattern_spec()); + + return pattern_predicate.Run(primary_pattern, secondary_pattern); + }; + SetGrants(BuildGrantsWithPredicate(reset_cohort)); +} + +namespace helpers { +std::string GenerateKeyHash(const MetadataEntry& metadata_entry) { + std::string key = base::StrCat( + {metadata_entry.primary_pattern_spec(), + /*Non-url delimiter:*/ "\\", metadata_entry.secondary_pattern_spec(), + base::NumberToString(ElectedDtrp(metadata_entry))}); + + // The hash from SHA1 is faster to obtain than SHA256 and will be forever + // unchanged if key is unchanged and provides lesser collision risk than MD5. + return base::Base64Encode(base::SHA1HashString(key)); +} +} // namespace helpers + } // namespace tpcd::metadata
diff --git a/components/tpcd/metadata/manager.h b/components/tpcd/metadata/manager.h index 06af481..cef4bd4 100644 --- a/components/tpcd/metadata/manager.h +++ b/components/tpcd/metadata/manager.h
@@ -5,11 +5,14 @@ #ifndef COMPONENTS_TPCD_METADATA_MANAGER_H_ #define COMPONENTS_TPCD_METADATA_MANAGER_H_ +#include <memory> + #include "base/functional/callback_helpers.h" #include "base/no_destructor.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/features.h" #include "components/content_settings/core/common/host_indexed_content_settings.h" +#include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" #include "components/tpcd/metadata/common/manager_base.h" #include "components/tpcd/metadata/parser.h" @@ -20,6 +23,11 @@ // fresh copy to the grants. using GrantsSyncCallback = base::RepeatingCallback<void(const ContentSettingsForOneType&)>; + +using PatternSourcePredicate = base::RepeatingCallback<bool( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern)>; + namespace tpcd::metadata { // TODO(b/333529481): Implement an observer pattern for the Manager class @@ -60,17 +68,46 @@ SetGrants(grants); } - protected: - // Generates a random number between (`Parser::kMinDtrp`, `Parser::kMaxDtrp`]. - virtual uint32_t GenerateRand() const; + // ResetCohorts only resets cohorts from any MetadataEntry matched by + // `pattern_predicate`. But If `pattern_predicate` is null, this method resets + // all the persisted cohorts. + void ResetCohorts(PatternSourcePredicate pattern_predicate); - std::string GenerateKeyHash(const MetadataEntry& metadata_entry) const; + class RandGenerator { + public: + RandGenerator() = default; + virtual ~RandGenerator() {} + + RandGenerator(const RandGenerator&) = delete; + RandGenerator& operator=(const RandGenerator&) = delete; + + virtual uint32_t Generate() const; + }; + + // SetRandGeneratorForTesting can be used at testing to set a deterministic + // random number generator. + void SetRandGeneratorForTesting(RandGenerator* generator) { + rand_generator_.reset(generator); + } + + // TODO(b/333529481): This shouldn't be needed for unittest relying i on the + // "forever" instance `this` after restructuring. + void SetPrefServiceForTesting(PrefService* local_state) { + local_state_ = local_state; + } private: friend base::NoDestructor<Manager>; void SetGrants(const ContentSettingsForOneType& grants); + // BuildGrantsWithPredicate builds TPCD Metadata grants based off of possibly + // persisted cohorts. The `predicate` function will determine whether to + // convey any persisted cohort for a given MetadataEntry into the final grant + // or to reset it. + ContentSettingsForOneType BuildGrantsWithPredicate( + base::FunctionRef<bool(const MetadataEntry&)> predicate); + // Parser::Observer: void OnMetadataReady() override; @@ -81,12 +118,17 @@ // `IsHostIndexedMetadataGrantsEnabled()` returns true, otherwise, it holds a // `ContentSettingsForOneType`. common::Grants grants_ GUARDED_BY(grants_lock_); + std::unique_ptr<RandGenerator> rand_generator_; // TODO(b/333529481): Get rid of this dangling pointer during re-architecture // of the code raw_ptr<PrefService, DisableDanglingPtrDetection> local_state_; }; +namespace helpers { +std::string GenerateKeyHash(const MetadataEntry& metadata_entry); +} + } // namespace tpcd::metadata #endif // COMPONENTS_TPCD_METADATA_MANAGER_H_
diff --git a/components/tpcd/metadata/manager_unittest.cc b/components/tpcd/metadata/manager_unittest.cc index 6e662ea..ad2debc 100644 --- a/components/tpcd/metadata/manager_unittest.cc +++ b/components/tpcd/metadata/manager_unittest.cc
@@ -22,6 +22,7 @@ #include "components/prefs/testing_pref_service.h" #include "components/tpcd/metadata/metadata.pb.h" #include "components/tpcd/metadata/parser.h" +#include "components/tpcd/metadata/parser_test_helper.h" #include "components/tpcd/metadata/prefs.h" #include "net/base/features.h" #include "testing/gmock/include/gmock/gmock.h" @@ -199,25 +200,6 @@ } } -class DeterministicManager : public Manager { - public: - DeterministicManager(Parser* parser, - GrantsSyncCallback callback, - PrefService* local_state) - : Manager(parser, callback, local_state) {} - ~DeterministicManager() override = default; - - // Returns a deterministic "random" value for testing. - uint32_t GenerateRand() const override { return rand_; } - - using Manager::GenerateKeyHash; - - void set_rand(uint32_t rand) { rand_ = rand; } - - private: - uint32_t rand_ = 0; -}; - class ManagerCohortsTest : public testing::Test, public testing::WithParamInterface<std::tuple<bool, int32_t>> { @@ -239,15 +221,6 @@ return manager_.get(); } - DeterministicManager* GetDeterministicManager( - GrantsSyncCallback callback = base::NullCallback()) { - if (!det_manager_) { - det_manager_ = std::make_unique<DeterministicManager>(GetParser(), - callback, nullptr); - } - return det_manager_.get(); - } - bool IsTpcdMetadataStagedRollbackEnabled() { return std::get<0>(GetParam()); } content_settings::mojom::TpcdMetadataRuleSource GetTpcdMetadataRuleSource() { return static_cast<content_settings::mojom::TpcdMetadataRuleSource>( @@ -298,7 +271,6 @@ // Guarantees proper tear down of dependencies. void TearDown() override { delete manager_.release(); - delete det_manager_.release(); delete parser_.release(); } @@ -306,7 +278,6 @@ base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<Parser> parser_; std::unique_ptr<Manager> manager_; - std::unique_ptr<DeterministicManager> det_manager_; }; INSTANTIATE_TEST_SUITE_P( @@ -345,6 +316,7 @@ EXPECT_EQ(rule_source, GetTpcdMetadataRuleSource()); switch (GetTpcdMetadataRuleSource()) { + case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_TEST: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_1P_DT: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_3P_DT: EXPECT_TRUE(Parser::IsDtrpEligible(rule_source)); @@ -354,7 +326,6 @@ SOURCE_CRITICAL_SECTOR: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_CUJ: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_GOV_EDU_TLD: - case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_TEST: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_UNSPECIFIED: EXPECT_FALSE(Parser::IsDtrpEligible(rule_source)); break; @@ -452,8 +423,9 @@ ToRuleSourceStr(GetTpcdMetadataRuleSource()), dtrp_being_tested); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand_being_tested); + Manager* manager = GetManager(); + manager->SetRandGeneratorForTesting( + new DeterministicGenerator(rand_being_tested)); GetParser()->ParseMetadata(metadata.SerializeAsString()); EXPECT_EQ(manager->GetGrants().size(), 1u); @@ -494,8 +466,9 @@ ToRuleSourceStr(GetTpcdMetadataRuleSource()), dtrp_being_tested); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand_being_tested); + Manager* manager = GetManager(); + manager->SetRandGeneratorForTesting( + new DeterministicGenerator(rand_being_tested)); GetParser()->ParseMetadata(metadata.SerializeAsString()); EXPECT_EQ(manager->GetGrants().size(), 1u); @@ -523,7 +496,10 @@ class ManagerPrefsTest : public testing::Test { public: - ManagerPrefsTest() = default; + ManagerPrefsTest() { + det_generator_ = new DeterministicGenerator(); + GetManager()->SetRandGeneratorForTesting(det_generator_); + } ~ManagerPrefsTest() override = default; Parser* GetParser() { @@ -541,13 +517,7 @@ return manager_.get(); } - DeterministicManager* GetDeterministicManager() { - if (!det_manager_) { - det_manager_ = std::make_unique<DeterministicManager>( - GetParser(), base::NullCallback(), &local_state_); - } - return det_manager_.get(); - } + DeterministicGenerator* GetDetGenerator() { return det_generator_; } PrefService* GetLocalState() { return &local_state_; } @@ -564,16 +534,16 @@ // Guarantees proper tear down of dependencies. void TearDown() override { + det_generator_ = nullptr; delete manager_.release(); - delete det_manager_.release(); delete parser_.release(); } private: base::test::ScopedFeatureList scoped_list_; + raw_ptr<DeterministicGenerator> det_generator_; std::unique_ptr<Parser> parser_; std::unique_ptr<Manager> manager_; - std::unique_ptr<DeterministicManager> det_manager_; TestingPrefServiceSimple local_state_; }; @@ -594,8 +564,8 @@ dtrp); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand); + Manager* manager = GetManager(); + GetDetGenerator()->set_rand(rand); GetParser()->ParseMetadata(metadata.SerializeAsString()); auto picked_cohort = @@ -607,7 +577,7 @@ const auto& dict = GetLocalState()->GetDict(prefs::kCohorts); EXPECT_EQ(dict.size(), 1u); EXPECT_EQ(dict.cbegin()->first, - manager->GenerateKeyHash(metadata.metadata_entries(0))); + helpers::GenerateKeyHash(metadata.metadata_entries(0))); EXPECT_EQ(dict.cbegin()->second, static_cast<int>(content_settings::mojom::TpcdMetadataCohort:: GRACE_PERIOD_FORCED_ON)); @@ -626,8 +596,8 @@ dtrp); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand); + Manager* manager = GetManager(); + GetDetGenerator()->set_rand(rand); GetParser()->ParseMetadata(metadata.SerializeAsString()); auto stored_cohort = @@ -639,7 +609,7 @@ const auto& dict = GetLocalState()->GetDict(prefs::kCohorts); EXPECT_EQ(dict.size(), 1u); EXPECT_EQ(dict.cbegin()->first, - manager->GenerateKeyHash(metadata.metadata_entries(0))); + helpers::GenerateKeyHash(metadata.metadata_entries(0))); EXPECT_EQ(dict.cbegin()->second, static_cast<int>(content_settings::mojom::TpcdMetadataCohort:: GRACE_PERIOD_FORCED_ON)); @@ -658,8 +628,8 @@ dtrp); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand); + Manager* manager = GetManager(); + GetDetGenerator()->set_rand(rand); GetParser()->ParseMetadata(metadata.SerializeAsString()); auto picked_cohort = @@ -671,7 +641,7 @@ const auto& dict = GetLocalState()->GetDict(prefs::kCohorts); EXPECT_EQ(dict.size(), 1u); EXPECT_EQ(dict.cbegin()->first, - manager->GenerateKeyHash(metadata.metadata_entries(0))); + helpers::GenerateKeyHash(metadata.metadata_entries(0))); EXPECT_EQ(dict.cbegin()->second, static_cast<int>(content_settings::mojom::TpcdMetadataCohort:: GRACE_PERIOD_FORCED_ON)); @@ -690,8 +660,8 @@ dtrp); EXPECT_EQ(metadata.metadata_entries_size(), 1); - DeterministicManager* manager = GetDeterministicManager(); - manager->set_rand(rand); + Manager* manager = GetManager(); + GetDetGenerator()->set_rand(rand); GetParser()->ParseMetadata(metadata.SerializeAsString()); auto picked_cohort = @@ -703,7 +673,7 @@ const auto& dict = GetLocalState()->GetDict(prefs::kCohorts); EXPECT_EQ(dict.size(), 1u); EXPECT_EQ(dict.cbegin()->first, - manager->GenerateKeyHash(metadata.metadata_entries(0))); + helpers::GenerateKeyHash(metadata.metadata_entries(0))); EXPECT_EQ(dict.cbegin()->second, static_cast<int>(content_settings::mojom::TpcdMetadataCohort:: GRACE_PERIOD_FORCED_OFF));
diff --git a/components/tpcd/metadata/parser.cc b/components/tpcd/metadata/parser.cc index f3f137c..0ab3190 100644 --- a/components/tpcd/metadata/parser.cc +++ b/components/tpcd/metadata/parser.cc
@@ -56,11 +56,11 @@ // static bool Parser::IsDtrpEligible(const TpcdMetadataRuleSource& rule_source) { switch (rule_source) { + case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_TEST: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_1P_DT: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_3P_DT: return true; case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_UNSPECIFIED: - case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_TEST: case content_settings::mojom::TpcdMetadataRuleSource::SOURCE_DOGFOOD: case content_settings::mojom::TpcdMetadataRuleSource:: SOURCE_CRITICAL_SECTOR: @@ -198,7 +198,7 @@ } helpers::AddEntryToMetadata(metadata, base::StrCat({"http://", hostname, ".test"}), - "*", Parser::kSourceTest); + "*", Parser::kSourceTest, /*dtrp=*/0); } CHECK(Parser::IsValidMetadata(metadata, base::NullCallback())); return metadata;
diff --git a/components/tpcd/metadata/parser_test_helper.cc b/components/tpcd/metadata/parser_test_helper.cc index eee8e11..dd0e5488 100644 --- a/components/tpcd/metadata/parser_test_helper.cc +++ b/components/tpcd/metadata/parser_test_helper.cc
@@ -16,4 +16,7 @@ return base::Base64Encode(compressed); } +uint32_t DeterministicGenerator::Generate() const { + return rand_; +} } // namespace tpcd::metadata
diff --git a/components/tpcd/metadata/parser_test_helper.h b/components/tpcd/metadata/parser_test_helper.h index 706b3c9f..6e5a344 100644 --- a/components/tpcd/metadata/parser_test_helper.h +++ b/components/tpcd/metadata/parser_test_helper.h
@@ -5,9 +5,27 @@ #ifndef COMPONENTS_TPCD_METADATA_PARSER_TEST_HELPER_H_ #define COMPONENTS_TPCD_METADATA_PARSER_TEST_HELPER_H_ +#include <cstdint> + +#include "components/tpcd/metadata/manager.h" #include "components/tpcd/metadata/metadata.pb.h" namespace tpcd::metadata { std::string MakeBase64EncodedMetadata(const Metadata& metadata); +class DeterministicGenerator : public Manager::RandGenerator { + public: + explicit DeterministicGenerator(const uint32_t rand = 0) : rand_(rand) {} + ~DeterministicGenerator() override = default; + + DeterministicGenerator(const DeterministicGenerator&) = delete; + DeterministicGenerator& operator=(const DeterministicGenerator&) = delete; + + uint32_t Generate() const override; + // Sets a deterministic number to be returned by the generator. + void set_rand(uint32_t rand) { rand_ = rand; } + + private: + uint32_t rand_; +}; } // namespace tpcd::metadata #endif // COMPONENTS_TPCD_METADATA_PARSER_TEST_HELPER_H_
diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn index e094a03..c0a098b 100644 --- a/components/user_manager/BUILD.gn +++ b/components/user_manager/BUILD.gn
@@ -29,6 +29,7 @@ ":common", "//base", "//components/account_id", + "//components/prefs", "//ui/gfx", ] @@ -71,7 +72,6 @@ "//ash/constants", "//chromeos/ash/components/install_attributes", "//chromeos/ash/components/settings", - "//components/prefs", "//skia", "//ui/base", "//ui/chromeos/resources",
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy.cc b/components/user_manager/multi_user/multi_user_sign_in_policy.cc index 16a6df9..830ad548 100644 --- a/components/user_manager/multi_user/multi_user_sign_in_policy.cc +++ b/components/user_manager/multi_user/multi_user_sign_in_policy.cc
@@ -6,6 +6,9 @@ #include "base/check_op.h" #include "base/containers/fixed_flat_map.h" +#include "components/prefs/pref_service.h" +#include "components/user_manager/user.h" +#include "components/user_manager/user_manager_pref_names.h" namespace user_manager { @@ -35,4 +38,19 @@ return std::nullopt; } +std::optional<MultiUserSignInPolicy> GetMultiUserSignInPolicy( + const User* user) { + if (!user) { + return std::nullopt; + } + + auto* prefs = user->GetProfilePrefs(); + if (!prefs) { + return std::nullopt; + } + + return ParseMultiUserSignInPolicyPref( + prefs->GetString(prefs::kMultiProfileUserBehaviorPref)); +} + } // namespace user_manager
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy.h b/components/user_manager/multi_user/multi_user_sign_in_policy.h index e843786..c7c71519 100644 --- a/components/user_manager/multi_user/multi_user_sign_in_policy.h +++ b/components/user_manager/multi_user/multi_user_sign_in_policy.h
@@ -12,6 +12,8 @@ namespace user_manager { +class User; + enum class MultiUserSignInPolicy { // The user is allowed to be either a primary user or secondary user in // multi user sign-in sessions. @@ -32,6 +34,11 @@ USER_MANAGER_EXPORT std::optional<MultiUserSignInPolicy> ParseMultiUserSignInPolicyPref(std::string_view s); +// Returns the policy for the given User. If the pref is not available +// returns std::nullopt. +USER_MANAGER_EXPORT std::optional<MultiUserSignInPolicy> +GetMultiUserSignInPolicy(const User* user); + } // namespace user_manager #endif // COMPONENTS_USER_MANAGER_MULTI_USER_MULTI_USER_SIGN_IN_POLICY_H_
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc index 09539b46..bf3dadb 100644 --- a/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc +++ b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.cc
@@ -34,22 +34,6 @@ pref_watchers_.clear(); } -std::optional<MultiUserSignInPolicy> -MultiUserSignInPolicyController::GetPrimaryUserPolicy() const { - const User* user = user_manager_->GetPrimaryUser(); - if (!user) { - return std::nullopt; - } - - auto* prefs = user->GetProfilePrefs(); - if (!prefs) { - return std::nullopt; - } - - return ParseMultiUserSignInPolicyPref( - prefs->GetString(prefs::kMultiProfileUserBehaviorPref)); -} - bool MultiUserSignInPolicyController::IsUserAllowedInSession( const std::string& user_email) const { const User* primary_user = user_manager_->GetPrimaryUser(); @@ -64,7 +48,7 @@ return true; } - auto primary_user_policy = GetPrimaryUserPolicy(); + auto primary_user_policy = GetMultiUserSignInPolicy(primary_user); if (primary_user_policy == MultiUserSignInPolicy::kNotAllowed) { return false; }
diff --git a/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h index f4f88671..b40439c6 100644 --- a/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h +++ b/components/user_manager/multi_user/multi_user_sign_in_policy_controller.h
@@ -47,10 +47,6 @@ // Returns the cached policy value for `user_email`. MultiUserSignInPolicy GetCachedValue(std::string_view user_email) const; - // Returns the primary user's policy. If there's no primary user, - // returns std::nullopt. - std::optional<MultiUserSignInPolicy> GetPrimaryUserPolicy() const; - // Returns true if user allowed to be in the current session. bool IsUserAllowedInSession(const std::string& user_email) const;
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn index 3218155..ec2ef92e 100644 --- a/components/vector_icons/BUILD.gn +++ b/components/vector_icons/BUILD.gn
@@ -11,7 +11,6 @@ sources = [ "${branding_path_component}/product.icon", - "${branding_path_component}/product_refresh.icon", "account_circle.icon", "account_circle_chrome_refresh.icon", "account_circle_off_chrome_refresh.icon", @@ -255,6 +254,14 @@ sources += [ "videogame_asset_outline.icon" ] } + # This is a temporary fix, will be reverted soon. + # TODO(http://b/335697556): Add product_refresh.icon to Chrome + # for Testing repo. + # No icon is provided for branded Chrome for testing builds. + if (!is_chrome_for_testing_branded) { + sources += [ "${branding_path_component}/product_refresh.icon" ] + } + if (is_chrome_branded) { sources += [ "google_chrome/google_calendar.icon",
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index f4d1d1e..682ad114 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -62,10 +62,10 @@ std::string* output, const scoped_refptr<base::RefCountedString>& json_events_str, bool has_more_events) { - if (output->size() > 1 && !json_events_str->data().empty()) { + if (output->size() > 1 && !json_events_str->as_string().empty()) { output->append(","); } - output->append(json_events_str->data()); + output->append(json_events_str->as_string()); if (!has_more_events) { std::move(quit_closure).Run(); }
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.cc b/components/viz/service/display_embedder/skia_output_device_dcomp.cc index efecae9..882e834 100644 --- a/components/viz/service/display_embedder/skia_output_device_dcomp.cc +++ b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
@@ -462,10 +462,10 @@ params->rounded_corner_bounds = dc_layer.rounded_corners; params->nearest_neighbor_filter = dc_layer.nearest_neighbor_filter; - params->protected_video_type = dc_layer.protected_video_type; - params->color_space = dc_layer.color_space; - params->hdr_metadata = dc_layer.hdr_metadata; - params->possible_video_fullscreen_letterboxing = + params->video_params.protected_video_type = dc_layer.protected_video_type; + params->video_params.color_space = dc_layer.color_space; + params->video_params.hdr_metadata = dc_layer.hdr_metadata; + params->video_params.possible_video_fullscreen_letterboxing = dc_layer.possible_video_fullscreen_letterboxing; // Schedule DC layer overlay to be presented at next SwapBuffers().
diff --git a/components/webapps/browser/installable/installable_icon_fetcher.cc b/components/webapps/browser/installable/installable_icon_fetcher.cc index eedb405e..ced7956 100644 --- a/components/webapps/browser/installable/installable_icon_fetcher.cc +++ b/components/webapps/browser/installable/installable_icon_fetcher.cc
@@ -99,7 +99,7 @@ SkBitmap decoded; if (bitmap_result.is_valid()) { base::AssertLongCPUWorkAllowed(); - gfx::PNGCodec::Decode(bitmap_result.bitmap_data->front(), + gfx::PNGCodec::Decode(bitmap_result.bitmap_data->data(), bitmap_result.bitmap_data->size(), &decoded); }
diff --git a/content/browser/background_fetch/storage/image_helpers.cc b/content/browser/background_fetch/storage/image_helpers.cc index dbee0df..cbd4c80 100644 --- a/content/browser/background_fetch/storage/image_helpers.cc +++ b/content/browser/background_fetch/storage/image_helpers.cc
@@ -21,11 +21,8 @@ constexpr int kMaxIconResolution = 256 * 256; std::string ConvertAndSerializeIcon(const SkBitmap& icon) { - std::string serialized_icon; auto icon_bytes = gfx::Image::CreateFrom1xBitmap(icon).As1xPNGBytes(); - serialized_icon.assign(icon_bytes->front_as<char>(), - icon_bytes->front_as<char>() + icon_bytes->size()); - return serialized_icon; + return std::string(base::as_string_view(*icon_bytes)); } SkBitmap DeserializeAndConvertIcon(
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc index 13dc3d4a..c837c64 100644 --- a/content/browser/devtools/devtools_agent_host_impl.cc +++ b/content/browser/devtools/devtools_agent_host_impl.cc
@@ -382,8 +382,7 @@ scoped_refptr<base::RefCountedMemory> data) { scoped_refptr<DevToolsStreamFile> stream = DevToolsStreamFile::Create(GetIOContext(), true /* binary */); - std::string text(reinterpret_cast<const char*>(data->front()), data->size()); - stream->Append(std::make_unique<std::string>(text)); + stream->Append(std::make_unique<std::string>(base::as_string_view(*data))); return stream->handle(); }
diff --git a/content/browser/devtools/devtools_frontend_host_impl.cc b/content/browser/devtools/devtools_frontend_host_impl.cc index 15e152fd..a94ceac 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.cc +++ b/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -99,7 +99,7 @@ scoped_refptr<base::RefCountedMemory> bytes = GetFrontendResourceBytes(path); if (!bytes) return std::string(); - return std::string(bytes->front_as<char>(), bytes->size()); + return std::string(base::as_string_view(*bytes)); } DevToolsFrontendHostImpl::DevToolsFrontendHostImpl(
diff --git a/content/browser/devtools/devtools_http_handler.cc b/content/browser/devtools/devtools_http_handler.cc index 724be96..2068552e 100644 --- a/content/browser/devtools/devtools_http_handler.cc +++ b/content/browser/devtools/devtools_http_handler.cc
@@ -701,11 +701,10 @@ scoped_refptr<base::RefCountedMemory> bytes = GetContentClient()->GetDataResourceBytes(kCcompressedProtocolJSON); CHECK(bytes) << "Could not load protocol"; - std::string json_protocol(reinterpret_cast<const char*>(bytes->front()), - bytes->size()); net::HttpServerResponseInfo response(net::HTTP_OK); - response.SetBody(json_protocol, "application/json; charset=UTF-8"); + response.SetBody(std::string(base::as_string_view(*bytes)), + "application/json; charset=UTF-8"); thread_->task_runner()->PostTask( FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc index 531f27b3..933ccce 100644 --- a/content/browser/devtools/devtools_url_loader_interceptor.cc +++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -217,7 +217,7 @@ private: void OnDataAvailable(const void* data, size_t num_bytes) override { DCHECK(!data_complete_); - body_->data().append( + body_->as_string().append( std::string(static_cast<const char*>(data), num_bytes)); } @@ -245,7 +245,7 @@ data_complete_ = true; body_pipe_drainer_.reset(); // TODO(caseq): only encode if necessary. - encoded_body_ = base::Base64Encode(body_->data()); + encoded_body_ = base::Base64Encode(*body_); for (auto& cb : callbacks_) cb->sendSuccess(encoded_body_, true); callbacks_.clear(); @@ -1229,11 +1229,10 @@ size_t bytes_to_sniff = std::min(body_size, static_cast<size_t>(net::kMaxBytesToSniff)); const std::string hint = head->mime_type; - net::SniffMimeType( - std::string_view(body->front_as<const char>() + response_body_offset, - bytes_to_sniff), - url, hint, net::ForceSniffFileUrlsForHtml::kDisabled, - &head->mime_type); + net::SniffMimeType(base::as_string_view(*body).substr( + response_body_offset, bytes_to_sniff), + url, hint, net::ForceSniffFileUrlsForHtml::kDisabled, + &head->mime_type); head->did_mime_sniff = true; } else if (head->mime_type.empty()) { head->mime_type.assign("text/plain"); @@ -1373,7 +1372,7 @@ if (body) { size_t num_bytes = body_size; MojoResult res = producer_handle->WriteData( - body->front() + offset, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE); + body->data() + offset, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE); DCHECK_EQ(0u, res); DCHECK_EQ(num_bytes, body_size); }
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc index 54ac8a06..377ea3cc 100644 --- a/content/browser/interest_group/interest_group_browsertest.cc +++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -410,17 +410,16 @@ NetworkResponder(const NetworkResponder&) = delete; NetworkResponder& operator=(const NetworkResponder&) = delete; - void RegisterNetworkResponse( - const std::string& url_path, - const std::string& body, - const std::string& mime_type = "application/json", - ResponseHeaders extra_response_headers = {}) { + void RegisterNetworkResponse(const std::string& url_path, + std::string_view body, + std::string_view mime_type = "application/json", + ResponseHeaders extra_response_headers = {}) { base::AutoLock auto_lock(response_map_lock_); Response response; response.body = body; response.mime_type = mime_type; response.extra_response_headers = std::move(extra_response_headers); - response_map_[url_path] = response; + response_map_[url_path] = std::move(response); } struct SubresourceResponse { @@ -5441,6 +5440,156 @@ } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, + RunAuctionWithTooLongDecisionLogicUrl) { + GURL url = embedded_https_test_server().GetURL("a.test", "/echo"); + url::Origin origin = url::Origin::Create(url); + + // Create almost-too-long and too-long seller script URLs. + std::string almost_too_long_seller_url_base = origin.GetURL().spec(); + GURL almost_too_long_seller_url = GURL( + almost_too_long_seller_url_base + + std::string(url::kMaxURLChars - almost_too_long_seller_url_base.size(), + '1')); + GURL too_long_seller_url = GURL(almost_too_long_seller_url.spec() + "2"); + ASSERT_EQ(too_long_seller_url.spec().size(), url::kMaxURLChars + 1); + + ASSERT_TRUE(NavigateToURL(shell(), url)); + + // Join an interest group. All that matters is it will bid, and has an ad. + ASSERT_EQ(kSuccess, + JoinInterestGroupAndVerify( + blink::TestInterestGroupBuilder( + /*owner=*/origin, + /*name=*/"cars") + .SetBiddingUrl(embedded_https_test_server().GetURL( + origin.host(), "/interest_group/bidding_logic.js")) + .SetAds({{{url, /*metadata=*/std::nullopt}}}) + .Build())); + + // Register a response for both the almost too long seller path and the too + // long seller path. Latter should never be requested, but if it is, the + // server should respond with a valid script, to make this test fail if that + // script is ever unexpectedly download and run. + const std::string_view kDecisionLogicScript = R"( + function scoreAd(adMetadata, bid, auctionConfig, trustedScoringSignals, + browserSignals) { + return bid; + };)"; + network_responder_->RegisterNetworkResponse(almost_too_long_seller_url.path(), + kDecisionLogicScript, + "application/javascript"); + network_responder_->RegisterNetworkResponse(too_long_seller_url.path(), + kDecisionLogicScript, + "application/javascript"); + + EXPECT_EQ(url, RunAuctionAndWaitForUrl( + JsReplace(R"({ + seller: $1, + decisionLogicURL: $2, + interestGroupBuyers: [$1] + })", + origin, almost_too_long_seller_url))); + + EXPECT_EQ(nullptr, RunAuctionAndWait(JsReplace(R"({ + seller: $1, + decisionLogicURL: $2, + interestGroupBuyers: [$1] + })", + origin, too_long_seller_url))); +} + +// Run two multi-seller auctions with two components. In the first auction, both +// components have too-long decision logic URLs, and there should be no winner. +// In the second auction, one component has a too-long URL. There should be a +// winner. +IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, + RunComponentAuctionWithTooLongDecisionLogicUrl) { + GURL url = embedded_https_test_server().GetURL("a.test", "/echo"); + url::Origin origin = url::Origin::Create(url); + + // Create too-long seller script URL. + std::string too_long_seller_url_base = origin.GetURL().spec(); + GURL too_long_seller_url = + GURL(too_long_seller_url_base + + std::string(url::kMaxURLChars - too_long_seller_url_base.size() + 1, + '1')); + ASSERT_EQ(too_long_seller_url.spec().size(), url::kMaxURLChars + 1); + + ASSERT_TRUE(NavigateToURL(shell(), url)); + + // Join an interest group. All that matters is it will bid, and has an ad. + ASSERT_EQ(kSuccess, + JoinInterestGroupAndVerify( + blink::TestInterestGroupBuilder( + /*owner=*/origin, + /*name=*/"cars") + .SetBiddingUrl(embedded_https_test_server().GetURL( + origin.host(), "/interest_group/bidding_logic.js")) + .SetAds({{{url, /*metadata=*/std::nullopt}}}) + .Build())); + + // Run an auction where both component auctions have too-long decision logic + // URLs. There should be no winner. + std::string auction_config = JsReplace( + R"({ + seller: $1, + decisionLogicURL: $2, + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction", + componentAuctions: + [{ + seller: $1, + decisionLogicURL: $3, + interestGroupBuyers: [$1], + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction" + }, + { + seller: $1, + decisionLogicURL: $3, + interestGroupBuyers: [$1], + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction" + }] + })", + origin, + embedded_https_test_server().GetURL(origin.host(), + "/interest_group/decision_logic.js"), + too_long_seller_url); + EXPECT_EQ(nullptr, RunAuctionAndWait(auction_config)); + + // Run an auction where only one component auction has a too-long decision + // logic URLs. There should be a winner from the other component auction. + std::string auction_config2 = JsReplace( + R"({ + seller: $1, + decisionLogicURL: $2, + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction", + componentAuctions: + [{ + seller: $1, + decisionLogicURL: $2, + interestGroupBuyers: [$1], + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction" + }, + { + seller: $1, + decisionLogicURL: $3, + interestGroupBuyers: [$1], + auctionSignals: "bidderAllowsComponentAuction,"+ + "sellerAllowsComponentAuction" + }] + })", + origin, + embedded_https_test_server().GetURL(origin.host(), + "/interest_group/decision_logic.js"), + too_long_seller_url); + EXPECT_EQ(url, RunAuctionAndWaitForUrl(auction_config2)); +} + +IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionPositiveMaxTrustedScoringSignalsURLLength) { GURL url = embedded_https_test_server().GetURL("a.test", "/echo"); url::Origin origin = url::Origin::Create(url); @@ -11586,7 +11735,7 @@ network_responder_->RegisterNetworkResponse(seller_logic_url.path(), R"( function scoreAd( adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) { - // Reject bits if trustedScoringSignals is not received. + // Reject bids if trustedScoringSignals is not received. if (trustedScoringSignals.renderURL[browserSignals.renderURL] === "foo") return bid; return 0;
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 811072e7..eea7a4fb 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -6044,71 +6044,6 @@ EXPECT_EQ(final_url, results[1].url); } -// Regression test for https://crbug.com/1223837. Previously, if a child frame -// was in the middle of committing a navigation to a provisional frame in render -// process B while render process A simultaneously detaches that child frame, -// the detach message would never be received by render process B. -IN_PROC_BROWSER_TEST_F(UndoCommitNavigationBrowserTest, - DetachAfterCommitNavigationInSubFrame) { - ASSERT_TRUE(NavigateToURL( - shell(), embedded_test_server()->GetURL( - "a.com", "/cross_site_iframe_factory.html?a(b,a)"))); - - WebContentsImpl* const web_contents = - static_cast<WebContentsImpl*>(shell()->web_contents()); - FrameTreeNode* const first_subframe_node = - web_contents->GetPrimaryMainFrame()->child_at(0); - FrameTreeNode* const second_subframe_node = - web_contents->GetPrimaryMainFrame()->child_at(1); - RenderProcessHost* const b_com_render_process_host = - first_subframe_node->render_manager()->current_frame_host()->GetProcess(); - - // Start a navigation in the second child frame that will create a speculative - // RFH in the existing render process for b.com. The first child frame is - // already hosted in the render process for b.com: this is to ensure the - // render process remains live even after the second child frame is detached - // later in this test. - ASSERT_TRUE(BeginNavigateToURLFromRenderer( - second_subframe_node, - embedded_test_server()->GetURL("b.com", "/title1.html"))); - - // Ensure the speculative RFH is in the expected process. - RenderFrameHostImpl* speculative_render_frame_host = - second_subframe_node->render_manager()->speculative_frame_host(); - ASSERT_TRUE(speculative_render_frame_host); - EXPECT_EQ(b_com_render_process_host, - speculative_render_frame_host->GetProcess()); - - // Pause (and ignore) the next `DidCommitProvisionalLoad()` for b.com. - CommitNavigationPauser commit_pauser(speculative_render_frame_host); - commit_pauser.WaitForCommitAndPause(); - - // At this point, the b.com renderer has already committed the RenderFrame, - // but on the browser side, the RenderFrameHost is still speculative. - - // Intentionally do not wait for script completion here. This runs an event - // loop that pumps incoming messages, but IPCs from b.com would be processed - // out of order, since the `DidCommitProvisionalLoad()` attempt was previously - // paused above. - ExecuteScriptAsync( - web_contents, - JsReplace("document.querySelectorAll('iframe')[1].remove()")); - - // However, since it's not possible to wait for `remove()` to take effect, - // the test must cheat a little and directly call the Mojo IPC that the JS - // above would eventually trigger. - second_subframe_node->render_manager()->current_frame_host()->Detach(); - - EXPECT_TRUE(WaitForLoadStop(web_contents)); - // Validate that render process for b.com has handled the detach message for - // the provisional frame that was committing. Before the fix, the render - // process for b.com still had the proxy for the second child frame, because - // the browser process's request to delete it was sent via a broken message - // pipe. Thus, the frame tree in the render process for b.com incorrectly - // thought there were still two child frames. - EXPECT_EQ(1, EvalJs(first_subframe_node, "top.length")); -} - class ResumeCommitClosureSetWaiter { public: explicit ResumeCommitClosureSetWaiter(NavigationHandle* handle) { @@ -6271,6 +6206,80 @@ base::test::ScopedFeatureList feature_list_; }; +// Test for https://crbug.com/40187807 and https://crbug.com/332746903. +// +// Ensure that racing a navigation commit in a speculative/provisional child +// frame in render process B with a detach IPC from render process A (i.e. the +// child frame's parent is in render process A and has removed the frame owner +// element—e.g. <iframe>—from the DOM) does not result in the detach IPC being +// discarded and never received by render process B. +IN_PROC_BROWSER_TEST_P(CommitNavigationRaceBrowserTest, + DetachAfterCommitNavigationInSubFrame) { + ASSERT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b,a)"))); + + WebContentsImpl* const web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + FrameTreeNode* const first_subframe_node = + web_contents->GetPrimaryMainFrame()->child_at(0); + FrameTreeNode* const second_subframe_node = + web_contents->GetPrimaryMainFrame()->child_at(1); + RenderProcessHost* const b_com_render_process_host = + first_subframe_node->render_manager()->current_frame_host()->GetProcess(); + + // Start a navigation in the second child frame that will create a speculative + // RFH in the existing render process for b.com. The first child frame is + // already hosted in the render process for b.com: this is to ensure the + // render process remains live even after the second child frame is detached + // later in this test. + ASSERT_TRUE(BeginNavigateToURLFromRenderer( + second_subframe_node, + embedded_test_server()->GetURL("b.com", "/title1.html"))); + + // Ensure the speculative RFH is in the expected process. + RenderFrameHostImpl* speculative_render_frame_host = + second_subframe_node->render_manager()->speculative_frame_host(); + ASSERT_TRUE(speculative_render_frame_host); + EXPECT_EQ(b_com_render_process_host, + speculative_render_frame_host->GetProcess()); + + // Pause (and ignore) the next `DidCommitProvisionalLoad()` for b.com. + CommitNavigationPauser commit_pauser(speculative_render_frame_host); + commit_pauser.WaitForCommitAndPause(); + + // At this point, the b.com renderer has already committed the RenderFrame, + // but on the browser side, the RenderFrameHost is still speculative. + + // Intentionally do not wait for script completion here. This runs an event + // loop that pumps incoming messages, but IPCs from b.com would be processed + // out of order, since the `DidCommitProvisionalLoad()` attempt was previously + // paused above. + ExecuteScriptAsync( + web_contents, + JsReplace("document.querySelectorAll('iframe')[1].remove()")); + + // However, since it's not possible to wait for `remove()` to take effect, + // the test must cheat a little and directly call the Mojo IPC that the JS + // above would eventually trigger. + second_subframe_node->render_manager()->current_frame_host()->Detach(); + + EXPECT_TRUE(WaitForLoadStop(web_contents)); + // Validate that render process for b.com has handled the detach message for + // the provisional frame that was committing. Before the fix: + // - without navigation queueing, the render process for b.com still had the + // proxy for the second child frame, because the browser process's request + // to delete it was sent via a broken message pipe. Thus, the frame tree in + // the render process for b.com incorrectly thought there were still two + // child frames. + // - with navigation queueing, the render process for b.com has already + // committed the navigation in the second child frame, so the renderer-side + // proxy has already been destroyed and replaced. However, the browser + // process has not heard about the commit yet and sends a detach to the + // proxy, which the renderer ignores since it no longer exists. + EXPECT_EQ(1, EvalJs(first_subframe_node, "top.length")); +} + IN_PROC_BROWSER_TEST_P(CommitNavigationRaceBrowserTest, BeginNewNavigationDuringCommitNavigationInMainFrame) { ASSERT_TRUE(NavigateToURL(
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc index eacf7fe..dca797b 100644 --- a/content/browser/payments/payment_app_provider_impl.cc +++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -84,8 +84,7 @@ gfx::Image decoded_image = gfx::Image::CreateFrom1xBitmap(app_icon); scoped_refptr<base::RefCountedMemory> raw_data = decoded_image.As1xPNGBytes(); - return base::Base64Encode( - std::string_view(raw_data->front_as<char>(), raw_data->size())); + return base::Base64Encode(*raw_data); } void CheckRegistrationSuccess(base::OnceCallback<void(bool success)> callback,
diff --git a/content/browser/renderer_host/cookie_utils.cc b/content/browser/renderer_host/cookie_utils.cc index 69fdade..ae97a548 100644 --- a/content/browser/renderer_host/cookie_utils.cc +++ b/content/browser/renderer_host/cookie_utils.cc
@@ -426,10 +426,6 @@ RenderFrameHostImpl* render_frame_host, NavigationRequest* navigation_request, const network::mojom::CookieAccessDetailsPtr& cookie_details) { - if (!base::FeatureList::IsEnabled( - features::kLegacyTechReportEnableCookieIssueReports)) { - return; - } CHECK(render_frame_host); for (const network::mojom::CookieOrLineWithAccessResultPtr& cookie :
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc index fad24f0..e57f8c14 100644 --- a/content/browser/renderer_host/navigation_controller_impl.cc +++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -2656,10 +2656,9 @@ // From the GURL's POV, the only important part here is scheme, it doesn't // check the actual content. Thus we can take only the prefix of the url, to // avoid unneeded copying of a potentially long string. - const size_t kDataUriPrefixMaxLen = 64; - GURL data_url( - std::string(data_url_as_string->front_as<char>(), - std::min(data_url_as_string->size(), kDataUriPrefixMaxLen))); + constexpr size_t kDataUriPrefixMaxLen = 64; + const size_t len = std::min(data_url_as_string->size(), kDataUriPrefixMaxLen); + GURL data_url(base::as_string_view(*data_url_as_string).substr(0u, len)); if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) return false; @@ -4035,7 +4034,7 @@ /*visited_link_salt=*/std::nullopt); #if BUILDFLAG(IS_ANDROID) if (ValidateDataURLAsString(params.data_url_as_string)) { - commit_params->data_url_as_string = params.data_url_as_string->data(); + commit_params->data_url_as_string = params.data_url_as_string->as_string(); } #endif
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc index a0825a5..487f0bb 100644 --- a/content/browser/renderer_host/navigation_entry_impl.cc +++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -473,7 +473,7 @@ scoped_refptr<base::RefCountedString> data_url) { if (data_url) { // A quick check that it's actually a data URL. - DCHECK(base::StartsWith(data_url->front_as<char>(), url::kDataScheme, + DCHECK(base::StartsWith(base::as_string_view(*data_url), url::kDataScheme, base::CompareCase::SENSITIVE)); } data_url_as_string_ = std::move(data_url); @@ -977,9 +977,10 @@ // main frames, because loadData* navigations can only happen on the main // frame. bool is_for_main_frame = (root_node()->frame_entry == &frame_entry); + scoped_refptr<const base::RefCountedString> string = GetDataURLAsString(); if (is_for_main_frame && - NavigationControllerImpl::ValidateDataURLAsString(GetDataURLAsString())) { - commit_params->data_url_as_string = GetDataURLAsString()->data(); + NavigationControllerImpl::ValidateDataURLAsString(string)) { + commit_params->data_url_as_string = string->as_string(); } #endif
diff --git a/content/browser/renderer_host/render_frame_host_delegate.cc b/content/browser/renderer_host/render_frame_host_delegate.cc index fe2f96f..410943a7 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.cc +++ b/content/browser/renderer_host/render_frame_host_delegate.cc
@@ -161,12 +161,6 @@ return nullptr; } -bool RenderFrameHostDelegate::ShowPopupMenu( - RenderFrameHostImpl* render_frame_host, - const gfx::Rect& bounds) { - return false; -} - std::vector<RenderFrameHostImpl*> RenderFrameHostDelegate::GetActiveTopLevelDocumentsInBrowsingContextGroup( RenderFrameHostImpl* render_frame_host) {
diff --git a/content/browser/renderer_host/render_frame_host_delegate.h b/content/browser/renderer_host/render_frame_host_delegate.h index 4e766c2..1e708fee 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.h +++ b/content/browser/renderer_host/render_frame_host_delegate.h
@@ -600,13 +600,6 @@ blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget); - // Returns true if the popup is shown through WebContentsObserver. Else, the - // Android / Mac flavors of `RenderViewHostDelegateView` will show the popup - // menu correspondingly, and `WebContentsViewChildFrame` will show the popup - // for Mac's GuestView. - virtual bool ShowPopupMenu(RenderFrameHostImpl* render_frame_host, - const gfx::Rect& bounds); - virtual void DidLoadResourceFromMemoryCache( RenderFrameHostImpl* source, const GURL& url,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 7446881..0d4e636 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7869,7 +7869,14 @@ return; } - if (delegate()->ShowPopupMenu(this, bounds)) { + if (delegate()->GetVisibility() != Visibility::VISIBLE) { + // Don't create popups for hidden tabs. https://crbug.com/1521345 + send_did_cancel(std::move(popup_client)); + return; + } + + if (show_popup_menu_callback_for_testing_) { + std::move(show_popup_menu_callback_for_testing_).Run(bounds); send_did_cancel(std::move(popup_client)); return; }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 95935735..141969c 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -2372,6 +2372,10 @@ void TextSelectionChanged(const std::u16string& text, uint32_t offset, const gfx::Range& range) override; + void set_show_popup_menu_callback_for_testing( + base::OnceCallback<void(const gfx::Rect&)> callback) { + show_popup_menu_callback_for_testing_ = std::move(callback); + } void ShowPopupMenu( mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client, const gfx::Rect& bounds, @@ -5173,6 +5177,9 @@ // nonce returned is unique. base::Uuid base_auction_nonce_; + base::OnceCallback<void(const gfx::Rect&)> + show_popup_menu_callback_for_testing_; + // WeakPtrFactories are the last members, to ensure they are destroyed before // all other fields of `this`. base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_{this};
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index 70abee3..e243303 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -2035,16 +2035,6 @@ "RenderFrameHostManager::UnsetSpeculativeRenderFrameHost", ChromeTrackEvent::kFrameTreeNodeInfo, *frame_tree_node_); - if (ShouldQueueNavigationsWhenPendingCommitRFHExists() && - speculative_render_frame_host_ - ->HasPendingCommitForCrossDocumentNavigation()) { - // With navigation queueing, pending commit navigations in speculative - // RenderFrameHosts shouldn't get deleted, unless the FrameTreeNode or - // renderer process is gone/will be gone soon. - CHECK(reason == NavigationDiscardReason::kRenderProcessGone || - reason == NavigationDiscardReason::kWillRemoveFrame); - } - speculative_render_frame_host_->GetProcess()->RemovePendingView(); if (speculative_render_frame_host_->lifecycle_state() == LifecycleStateImpl::kSpeculative) { @@ -2054,8 +2044,10 @@ : mojom::FrameDeleteIntention:: kSpeculativeMainFrameForNavigationCancelled); } else { + // TODO(dcheng): Upgrade this to a CHECK()? DCHECK_EQ(speculative_render_frame_host_->lifecycle_state(), LifecycleStateImpl::kPendingCommit); + if (!ShouldQueueNavigationsWhenPendingCommitRFHExists()) { // The browser process already asked the renderer to commit the // navigation. The renderer is guaranteed to commit the navigation and @@ -2082,8 +2074,64 @@ speculative_render_frame_host_->UndoCommitNavigation( *proxy, frame_tree_node_->IsLoading()); } else { - speculative_render_frame_host_->SetLifecycleState( - LifecycleStateImpl::kReadyToBeDeleted); + // A reasonable person might wonder: shouldn't a RenderFrameHostImpl in + // kPendingCommit always have a... pending commit? + // + // The surprising answer is no! When the browser process handles the + // renderer's commit navigation ack: + // - the NavigationRequest is unconditionally removed from + // `RenderFrameHostImpl::navigation_requests_`. + // - but if the IPC fails validation, the browser process reports a bad + // message (which kills the renderer process) and returns immediately. + // + // However, the kill is async and observing process termination (which is + // what cleans up the speculative RenderFrameHostImpl) is also async. + // Between reporting the bad message and the actual cleanup, the user can + // begin a new navigation, which will discard any speculative RFHs rather + // than blocking (since `HasPendingCommitForCrossDocumentNavigation()` now + // returns `false`!) for a reason other than `kRenderProcessGone` or + // `kWillRemoveFrame`. + // + // TODO(dcheng): it might help make state easier to reason about if the + // speculative RFH is proactively discarded rather than just leaving it + // around to be asynchronously cleaned up. + if (speculative_render_frame_host_ + ->HasPendingCommitForCrossDocumentNavigation()) { + // With navigation queueing, pending commit navigations in speculative + // RenderFrameHosts shouldn't get deleted, unless the FrameTreeNode or + // renderer process is gone/will be gone soon. + CHECK(reason == NavigationDiscardReason::kRenderProcessGone || + reason == NavigationDiscardReason::kWillRemoveFrame); + } + + // TODO(dcheng): `CHECK(render_frame_host_->IsPendingDeletion())` would be + // a nice precondition to enforce here. However, this turns out to be + // Hard: `StartPendingDeletionOnSubtree()` performs its work in two + // phases: it resets all navigation requests first (which might delete + // speculative RFHs—even ones in pending commit), before doing a complex + // dance to invoke `DeleteRenderFrame()` a minimal number of times. In the + // future, it would be nice to refactor the code so this precondition can + // be enforced. + + // A pending commit RFH is assumed/expected to have committed already in + // the renderer process. If the FrameTreeNode is going away, explicitly + // tear down the RenderFrame in the renderer process to keep the frame + // tree in sync. + if (frame_tree_node_->parent()) { + speculative_render_frame_host_->DeleteRenderFrame( + mojom::FrameDeleteIntention::kNotMainFrame); + } else { + // But for main frames, just advance the lifecycle state instead. In + // Blink, a live WebView must always have a live main frame; violating + // this invariant by destroying the already-committed (from the + // perspective of the renderer process) frame with `DeleteRenderFrame()` + // results in bugs like crbug.com/40091257. + // + // The main RenderFrame will be implicitly torn down later when the + // corresponding RenderViewHost/WebView are torn down. + speculative_render_frame_host_->SetLifecycleState( + LifecycleStateImpl::kReadyToBeDeleted); + } } }
diff --git a/content/browser/resources/traces_internals/trace_report.html b/content/browser/resources/traces_internals/trace_report.html index 6c26f11..f16cddc 100644 --- a/content/browser/resources/traces_internals/trace_report.html +++ b/content/browser/resources/traces_internals/trace_report.html
@@ -1,7 +1,7 @@ <style include="cr-hidden-style"> .trace-card { display: grid; - grid-auto-columns: 1fr; + grid-template-columns: 1fr 1fr 1fr 3fr auto auto auto; grid-auto-flow: column; grid-column-gap: 12px; grid-row-gap: 0px; @@ -17,22 +17,17 @@ } .trace-card > div { - white-space: nowrap; overflow: hidden; min-width: 0; } - .trace-id-container, - .trace-upload-state-container { - grid-column: span 2; - } - - .trace-size-container { - width: 120px; - } - /* remove default button styling */ .clickable-field { + text-align: start; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; background: none; color: inherit; border: none; @@ -47,8 +42,10 @@ } .trace-upload-state-container { + white-space: nowrap; display: flex; flex-direction: column; + font-weight: bold; } .upload-state-card { @@ -125,26 +122,8 @@ } } - .skip-reason { - margin-top: 4px; - margin-left: 2px; - font-size: 10px; - color: var(--cr-secondary-text-color); - } - - .upload-action { - display: flex; - width: 64px; - justify-content: flex-end; - } - - .upload-action > .action-button { - margin-left: 0; - margin-right: 4px; - } - .actions-container { - width: 160px; + width: 150px; } .action-button { @@ -158,11 +137,6 @@ background-color: WhiteSmoke; } - .upload-button-container { - width: 50px; - display: inline-block; - } - .info { font-size: 13px; color: var(--cr-secondary-text-color); @@ -174,11 +148,6 @@ color: var(--cr-primary-text-color) } - - .trace-upload-state-container { - font-weight: bold; - } - .trace-spinner { position: absolute; width: 100%; @@ -204,7 +173,8 @@ </div> </template> <div class="trace-id-container"> - <button class="clickable-field copiable" on-click="onCopyUuidClick_"> + <button class="clickable-field copiable" + on-click="onCopyUuidClick_" title="[[tokenToString_(trace.uuid)]]"> [[tokenToString_(trace.uuid)]] </button> <div class="info">Trace ID</div> @@ -214,12 +184,14 @@ <div class="info">Date created</div> </div> <div class="trace-scenario-container"> - <button class="clickable-field copiable" on-click="onCopyScenarioClick_"> + <button class="clickable-field copiable" + on-click="onCopyScenarioClick_" title="[[trace.scenarioName]]"> [[trace.scenarioName]] </button> </div> <div class="trace-trigger-container"> - <button class="clickable-field copiable" on-click="onCopyUploadRuleClick_"> + <button class="clickable-field copiable" + on-click="onCopyUploadRuleClick_" title="[[trace.uploadRuleName]]"> [[trace.uploadRuleName]] </button> <div class="info">Trigger rule</div> @@ -252,15 +224,13 @@ </div> </div> <div class="actions-container"> - <div class="upload-button-container"> - <cr-icon-button class="action-button" title="Upload Trace" - iron-icon="trace-report-icons:cloud_upload" aria-label="Upload Trace" - on-click="onUploadTraceClick_" - hidden="[[!uploadStateEqual(trace.uploadState, - uploadStateEnum_.NOT_UPLOADED)]]" - disabled="[[!isManualUploadPermitted_(trace.skipReason)]]"> - </cr-icon-button> - </div> + <cr-icon-button class="action-button" title="Upload Trace" + iron-icon="trace-report-icons:cloud_upload" aria-label="Upload Trace" + on-click="onUploadTraceClick_" + hidden="[[!uploadStateEqual(trace.uploadState, + uploadStateEnum_.NOT_UPLOADED)]]" + disabled="[[!isManualUploadPermitted_(trace.skipReason)]]"> + </cr-icon-button> <cr-icon-button class="action-button" iron-icon="cr:file-download" title="Download Trace" on-click="onDownloadTraceClick_" disabled="[[isDownloadDisabled_(isLoading, trace.uploadState)]]"
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index 3623029a..20715495 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -196,7 +196,7 @@ // Called on any thread. void OnTraceData(base::OnceClosure stop_complete_callback, const scoped_refptr<base::RefCountedString>& events) { - if (!events || events->data().empty()) { + if (!events || events->as_string().empty()) { OnTraceDataCommitted(std::move(stop_complete_callback)); return; }
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc index 9063166..1d0992c5 100644 --- a/content/browser/tracing/tracing_ui.cc +++ b/content/browser/tracing/tracing_ui.cc
@@ -58,7 +58,7 @@ } auto res = base::MakeRefCounted<base::RefCountedString>(); - base::JSONWriter::Write(category_list, &res->data()); + base::JSONWriter::Write(category_list, &res->as_string()); std::move(callback).Run(res); } @@ -144,7 +144,7 @@ void TracingCallbackWrapperBase64(WebUIDataSource::GotDataCallback callback, std::unique_ptr<std::string> data) { base::RefCountedString* data_base64 = new base::RefCountedString(); - data_base64->data() = base::Base64Encode(*data); + data_base64->as_string() = base::Base64Encode(*data); std::move(callback).Run(data_base64); }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 6f5660c..2caed14 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -10193,28 +10193,6 @@ last_screen_orientation_change_time_ = ui::EventTimeForNow(); } -// TODO(crbug.com/328100331): This method should be renamed since it doesn't -// actually show a popup menu. -bool WebContentsImpl::ShowPopupMenu(RenderFrameHostImpl* render_frame_host, - const gfx::Rect& bounds) { - OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::ShowPopupMenu", - "render_frame_host", render_frame_host); - - if (visibility_ != Visibility::VISIBLE) { - // Don't create popups for hidden tabs. http://crbug.com/1521345 - // Returning true here makes RenderFrameHostImpl::ShowPopupMenu abort - // before showing a popup. - return true; - } - - DCHECK(render_frame_host->IsActive()); - if (show_popup_menu_callback_) { - std::move(show_popup_menu_callback_).Run(bounds); - return true; - } - return false; -} - void WebContentsImpl::UpdateWebContentsVisibility(Visibility visibility) { OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::UpdateWebContentsVisibility",
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 991ac5d..5490e902 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -821,8 +821,6 @@ blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) override; - bool ShowPopupMenu(RenderFrameHostImpl* render_frame_host, - const gfx::Rect& bounds) override; void DidLoadResourceFromMemoryCache( RenderFrameHostImpl* source, const GURL& url, @@ -1401,11 +1399,6 @@ }; CaptureTarget GetCaptureTarget(); - void set_show_popup_menu_callback_for_testing( - base::OnceCallback<void(const gfx::Rect&)> callback) { - show_popup_menu_callback_ = std::move(callback); - } - // Sets the value in tests to ensure expected ordering and correctness. void set_minimum_delay_between_loading_updates_for_testing( base::TimeDelta duration) { @@ -2429,8 +2422,6 @@ viz::FrameSinkId xr_render_target_; - base::OnceCallback<void(const gfx::Rect&)> show_popup_menu_callback_; - // Allows the app in the current WebContents to opt-in to exposing // information to apps that capture it. blink::mojom::CaptureHandleConfig capture_handle_config_;
diff --git a/content/browser/webui/web_ui_data_source_unittest.cc b/content/browser/webui/web_ui_data_source_unittest.cc index 02f8fc3..8d39fbe 100644 --- a/content/browser/webui/web_ui_data_source_unittest.cc +++ b/content/browser/webui/web_ui_data_source_unittest.cc
@@ -94,7 +94,7 @@ void EmptyStringsCallback(bool from_js_module, scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find("loadTimeData.data = {"), std::string::npos); EXPECT_NE(result.find("};"), std::string::npos); bool has_import = result.find("import {loadTimeData}") != std::string::npos; @@ -112,7 +112,7 @@ } void SomeValuesCallback(scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find("\"flag\":true"), std::string::npos); EXPECT_NE(result.find("\"counter\":10"), std::string::npos); EXPECT_NE(result.find("\"debt\":-456"), std::string::npos); @@ -133,13 +133,13 @@ } void DefaultResourceFoobarCallback(scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyDefaultResource), std::string::npos); } void DefaultResourceStringsCallback( scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyDefaultResource), std::string::npos); } @@ -151,12 +151,12 @@ } void NamedResourceFoobarCallback(scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyResource), std::string::npos); } void NamedResourceStringsCallback(scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyDefaultResource), std::string::npos); } @@ -169,7 +169,7 @@ void NamedResourceWithQueryStringCallback( scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyResource), std::string::npos); } @@ -183,7 +183,7 @@ void NamedResourceWithUrlFragmentCallback( scoped_refptr<base::RefCountedMemory> data) { EXPECT_NE(data, nullptr); - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyResource), std::string::npos); } @@ -195,7 +195,7 @@ void WebUIDataSourceTest::RequestFilterQueryStringCallback( scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); // Check that the query string is passed to the request filter (and not // trimmed). EXPECT_EQ("foobar?query?string", request_path_); @@ -282,7 +282,7 @@ } void NamedResourceBarJSCallback(scoped_refptr<base::RefCountedMemory> data) { - std::string result(data->front_as<char>(), data->size()); + std::string result(base::as_string_view(*data)); EXPECT_NE(result.find(kDummyJSResource), std::string::npos); }
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc index 3879322..3a9a162e 100644 --- a/content/browser/webui/web_ui_url_loader_factory.cc +++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -81,8 +81,7 @@ if (replacements) { // We won't know the the final output size ahead of time, so we have to // use an intermediate string. - std::string_view input(reinterpret_cast<const char*>(bytes->front()), - bytes->size()); + auto input = base::as_string_view(*bytes); std::string temp_str; if (replace_in_js) { CHECK(
diff --git a/content/browser/webui/web_ui_url_loader_factory_unittest.cc b/content/browser/webui/web_ui_url_loader_factory_unittest.cc index 9797c24a..78ec7de2 100644 --- a/content/browser/webui/web_ui_url_loader_factory_unittest.cc +++ b/content/browser/webui/web_ui_url_loader_factory_unittest.cc
@@ -97,11 +97,12 @@ delete; // base::RefCountedMemory implementation: - const unsigned char* front() const override { - NOTREACHED(); - return nullptr; + base::span<const uint8_t> AsSpan() const override { + // SAFETY: This is unsound, but any use of the pointer will crash as the + // first page is not mapped. The test does not actually use the pointer. + return UNSAFE_BUFFERS(base::span<const uint8_t>( + static_cast<const uint8_t*>(nullptr), size_)); } - size_t size() const override { return size_; } private: ~OversizedRefCountedMemory() override = default;
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 0de10e2..1af1c62 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -296,8 +296,6 @@ raw_ref(features::kTouchDragAndContextMenu)}, {wf::EnableUserActivationSameOriginVisibility, raw_ref(features::kUserActivationSameOriginVisibility)}, - {wf::EnableVideoPlaybackQuality, - raw_ref(features::kVideoPlaybackQuality)}, {wf::EnableWebBluetooth, raw_ref(features::kWebBluetooth), kSetOnlyIfOverridden}, {wf::EnableWebBluetoothGetDevices,
diff --git a/content/common/features.cc b/content/common/features.cc index 6531ca9a..6c577ae 100644 --- a/content/common/features.cc +++ b/content/common/features.cc
@@ -227,7 +227,7 @@ // renderer side for iframe creation. BASE_FEATURE(kFrameRoutingCache, "FrameRoutingCache", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); const base::FeatureParam<int> kFrameRoutingCacheResponseSize{ &kFrameRoutingCache, "responseSize", 4}; @@ -532,11 +532,6 @@ "TrustedTypesFromLiteral", base::FEATURE_DISABLED_BY_DEFAULT); -// Controls whether the <video>.getVideoPlaybackQuality() API is enabled. -BASE_FEATURE(kVideoPlaybackQuality, - "VideoPlaybackQuality", - base::FEATURE_ENABLED_BY_DEFAULT); - // Pre-warm up the network process on browser startup. #if BUILDFLAG(IS_ANDROID) BASE_FEATURE(kWarmUpNetworkProcess,
diff --git a/content/common/features.h b/content/common/features.h index fe9dc949..964c40f 100644 --- a/content/common/features.h +++ b/content/common/features.h
@@ -120,7 +120,6 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kTouchpadAsyncPinchEvents); CONTENT_EXPORT BASE_DECLARE_FEATURE(kTouchpadOverscrollHistoryNavigation); CONTENT_EXPORT BASE_DECLARE_FEATURE(kTrustedTypesFromLiteral); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kVideoPlaybackQuality); #if BUILDFLAG(IS_ANDROID) CONTENT_EXPORT BASE_DECLARE_FEATURE(kWarmUpNetworkProcess); #endif
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc index c558c75..1045f21 100644 --- a/content/public/common/content_client.cc +++ b/content/public/common/content_client.cc
@@ -125,7 +125,7 @@ GetDataResourceBytes(resource_id); if (!memory) return std::string(); - return std::string(memory->front_as<char>(), memory->size()); + return std::string(base::as_string_view(*memory)); } gfx::Image& ContentClient::GetNativeImageNamed(int resource_id) {
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index bdf2d14..d9e3f73 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -514,11 +514,6 @@ "LazyInitializeMediaControls", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables reporting of Cookie Issues for Legacy Technology Report. -BASE_FEATURE(kLegacyTechReportEnableCookieIssueReports, - "LegacyTechReportEnableCookieIssueReports", - base::FEATURE_ENABLED_BY_DEFAULT); - // Configures whether Blink on Windows 8.0 and below should use out of process // API font fallback calls to retrieve a fallback font family name as opposed to // using a hard-coded font lookup table.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 08ccda1d..a94fe21e 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -118,7 +118,6 @@ CONTENT_EXPORT extern const char kIsolateOriginsFieldTrialParamName[]; CONTENT_EXPORT BASE_DECLARE_FEATURE(kJavaScriptExperimentalSharedMemory); CONTENT_EXPORT BASE_DECLARE_FEATURE(kLazyInitializeMediaControls); -CONTENT_EXPORT BASE_DECLARE_FEATURE(kLegacyTechReportEnableCookieIssueReports); CONTENT_EXPORT BASE_DECLARE_FEATURE(kLegacyWindowsDWriteFontFallback); CONTENT_EXPORT BASE_DECLARE_FEATURE(kLogJsConsoleMessages); CONTENT_EXPORT BASE_DECLARE_FEATURE(kLowerPAMemoryLimitForNonMainRenderers);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index e6ece0d2..b726126e 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -415,8 +415,8 @@ net::GZipHeader::Status header_status = net::GZipHeader::INCOMPLETE_HEADER; const char* header_end = nullptr; while (header_status == net::GZipHeader::INCOMPLETE_HEADER) { - header_status = header.ReadMore(maybe_gzipped.front_as<char>(), - maybe_gzipped.size(), &header_end); + auto chars = base::as_chars(base::span(maybe_gzipped)); + header_status = header.ReadMore(chars.data(), chars.size(), &header_end); } return header_status == net::GZipHeader::COMPLETE_HEADER; } @@ -424,11 +424,13 @@ void AppendGzippedResource(const base::RefCountedMemory& encoded, std::string* to_append) { auto source_stream = std::make_unique<net::MockSourceStream>(); - source_stream->AddReadResult(encoded.front_as<char>(), encoded.size(), + auto encoded_chars = base::as_chars(base::span(encoded)); + source_stream->AddReadResult(encoded_chars.data(), encoded_chars.size(), net::OK, net::MockSourceStream::SYNC); // Add an EOF. - source_stream->AddReadResult(encoded.front_as<char>() + encoded.size(), 0, - net::OK, net::MockSourceStream::SYNC); + auto end = encoded_chars.last(0u); + source_stream->AddReadResult(end.data(), end.size(), net::OK, + net::MockSourceStream::SYNC); std::unique_ptr<net::GzipSourceStream> filter = net::GzipSourceStream::Create( std::move(source_stream), net::SourceStream::TYPE_GZIP); scoped_refptr<net::IOBufferWithSize> dest_buffer = @@ -1913,10 +1915,12 @@ ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes( IDR_ASH_WEBUI_COMMON_WEBUI_RESOURCE_TEST_JS); - if (HasGzipHeader(*bytes)) + if (HasGzipHeader(*bytes)) { AppendGzippedResource(*bytes, &script); - else - script.append(bytes->front_as<char>(), bytes->size()); + } else { + auto chars = base::as_chars(base::span(*bytes)); + script.append(chars.data(), chars.size()); + } script.append("\n"); ExecuteScriptAsync(web_contents, script);
diff --git a/content/public/test/web_ui_browsertest_util.cc b/content/public/test/web_ui_browsertest_util.cc index c0baed3..d08d27c 100644 --- a/content/public/test/web_ui_browsertest_util.cc +++ b/content/public/test/web_ui_browsertest_util.cc
@@ -49,7 +49,7 @@ CHECK(base::ReadFileToString(path, &contents)) << path.value(); base::RefCountedString* ref_contents = new base::RefCountedString; - ref_contents->data() = contents; + ref_contents->as_string() = contents; std::move(callback).Run(ref_contents); }
diff --git a/content/renderer/accessibility/annotations/ax_image_annotator.cc b/content/renderer/accessibility/annotations/ax_image_annotator.cc index bb6c8a4..881bcff 100644 --- a/content/renderer/accessibility/annotations/ax_image_annotator.cc +++ b/content/renderer/accessibility/annotations/ax_image_annotator.cc
@@ -179,7 +179,7 @@ } // Don't count ignored nodes toward depth. - int next_depth = obj.AccessibilityIsIgnored() ? max_depth : max_depth - 1; + int next_depth = obj.IsIgnored() ? max_depth : max_depth - 1; // Recurse. for (unsigned int i = 0; i < obj.ChildCount(); i++) { @@ -299,7 +299,7 @@ static const int kMinImageAnnotationHeight = 16; // Reject ignored objects - if (src.AccessibilityIsIgnored()) { + if (src.IsIgnored()) { return; } @@ -666,7 +666,7 @@ blink::WebAXObject parent = image.ParentObject(); for (int ancestor_count = 0; !parent.IsDetached() && ancestor_count < 2; parent = parent.ParentObject()) { - if (!parent.AccessibilityIsIgnored()) { + if (!parent.IsIgnored()) { ++ancestor_count; if (ui::IsLink(parent.Role()) || ui::IsPlatformDocument(parent.Role())) { render_accessibility_->MarkWebAXObjectDirty(parent);
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index 02703a6..9b6b015 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -431,7 +431,7 @@ ax::mojom::Action event_from_action, std::vector<ui::AXEventIntent> event_intents, ax::mojom::Event event_type) { - DCHECK(obj.AccessibilityIsIncludedInTree()) + DCHECK(obj.IsIncludedInTree()) << "Cannot serialize unincluded object: " << obj.ToString().Utf8(); obj.AddDirtyObjectToSerializationQueue(event_from, event_from_action,
diff --git a/content/services/auction_worklet/trusted_signals_request_manager.cc b/content/services/auction_worklet/trusted_signals_request_manager.cc index 28491bf..0cc849c 100644 --- a/content/services/auction_worklet/trusted_signals_request_manager.cc +++ b/content/services/auction_worklet/trusted_signals_request_manager.cc
@@ -373,6 +373,11 @@ // No need to continue running the timer, if it's running. timer_.Stop(); + if (fetches_paused_) { + deferred_start_batch_due_to_fetch_pause_ = true; + return; + } + std::unique_ptr<TrustedSignalsUrlBuilder> url_builder; bool split_fetch = base::FeatureList::IsEnabled( blink::features::kFledgeSplitTrustedSignalsFetchingURL); @@ -401,6 +406,19 @@ return; } +void TrustedSignalsRequestManager::Pause() { + fetches_paused_ = true; +} + +void TrustedSignalsRequestManager::Resume() { + DCHECK(fetches_paused_); + fetches_paused_ = false; + if (deferred_start_batch_due_to_fetch_pause_) { + deferred_start_batch_due_to_fetch_pause_ = false; + StartBatchedTrustedSignalsRequest(); + } +} + TrustedSignalsRequestManager::RequestImpl::RequestImpl( TrustedSignalsRequestManager* trusted_signals_request_manager, const std::string& interest_group_name, @@ -518,13 +536,9 @@ } void TrustedSignalsRequestManager::QueueRequest(RequestImpl* request) { - // If the timer is not running, then either `automatically_send_requests_` - // is false, or no requests should be in `queued_requests_`. - DCHECK_EQ(timer_.IsRunning(), - automatically_send_requests_ && !queued_requests_.empty()); - queued_requests_.insert(request); - if (automatically_send_requests_ && !timer_.IsRunning()) { + if (automatically_send_requests_ && + !deferred_start_batch_due_to_fetch_pause_ && !timer_.IsRunning()) { timer_.Start( FROM_HERE, kAutoSendDelay, base::BindOnce(
diff --git a/content/services/auction_worklet/trusted_signals_request_manager.h b/content/services/auction_worklet/trusted_signals_request_manager.h index 194efec..fc882b6 100644 --- a/content/services/auction_worklet/trusted_signals_request_manager.h +++ b/content/services/auction_worklet/trusted_signals_request_manager.h
@@ -137,6 +137,12 @@ const GURL& trusted_signals_url() const { return trusted_signals_url_; } + // If Pause() is called, no actual fetches will happen until Resume() is + // invoked. If any fetches would have started during the window between + // Pause() and Resume(), Resume() will kick things off immediately. + void Pause(); + void Resume(); + private: struct BatchedTrustedSignalsRequest; @@ -250,6 +256,16 @@ base::UniquePtrComparator> batched_requests_; + // If this is true, outgoing requests will not be made until Resume() is + // called; instead we merely denote that we were going to do so in + // `deferred_start_batch_due_to_fetch_pause_`. + bool fetches_paused_ = false; + + // This is set if StartBatchedTrustedSignalsRequest() got called when + // Pause()d, and denotes that queued fetches should be issued as soon as + // Resume() is called. + bool deferred_start_batch_due_to_fetch_pause_ = false; + base::OneShotTimer timer_; mojo::Remote<auction_worklet::mojom::AuctionNetworkEventsHandler>
diff --git a/content/services/auction_worklet/trusted_signals_request_manager_unittest.cc b/content/services/auction_worklet/trusted_signals_request_manager_unittest.cc index fcc98448..6b29d25 100644 --- a/content/services/auction_worklet/trusted_signals_request_manager_unittest.cc +++ b/content/services/auction_worklet/trusted_signals_request_manager_unittest.cc
@@ -955,6 +955,110 @@ kAdComponentRenderUrls3)); } +// Test of Pause()/Resume() with explicitly controlled batches. +TEST_F(TrustedSignalsRequestManagerTest, ScoringSignalsBatchedRequestsPause) { + scoring_request_manager_.Pause(); + + const GURL kRenderUrl1 = GURL("https://foo.test/"); + const std::vector<std::string> kAdComponentRenderUrls1{ + "https://foosub.test/", "https://bazsub.test/"}; + + const GURL kRenderUrl2 = GURL("https://bar.test/"); + const std::vector<std::string> kAdComponentRenderUrls2{ + "https://barsub.test/", "https://bazsub.test/"}; + + base::RunLoop run_loop1; + scoped_refptr<TrustedSignals::Result> signals1; + std::optional<std::string> error_msg1; + auto request1 = scoring_request_manager_.RequestScoringSignals( + kRenderUrl1, kAdComponentRenderUrls1, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals1, &error_msg1, + run_loop1.QuitClosure())); + + base::RunLoop run_loop2; + scoped_refptr<TrustedSignals::Result> signals2; + std::optional<std::string> error_msg2; + auto request2 = scoring_request_manager_.RequestScoringSignals( + kRenderUrl2, kAdComponentRenderUrls2, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals2, &error_msg2, + run_loop2.QuitClosure())); + + scoring_request_manager_.StartBatchedTrustedSignalsRequest(); + task_environment_.RunUntilIdle(); + // Nothing issued yet despite explicit StartBatchedTrustedSignalsRequest() + // since we're paused. + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Queued fetches get issued after resume. + scoring_request_manager_.Resume(); + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse( + &url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Fbar.test%2F,https%3A%" + "2F%2Ffoo.test%2F&adComponentRenderUrls=https%3A%2F%2Fbarsub.test%" + "2F,https%3A%2F%2Fbazsub.test%2F,https%3A%2F%2Ffoosub.test%2F"), + kBaseScoringJson); + + run_loop1.Run(); + EXPECT_FALSE(error_msg1); + ASSERT_TRUE(signals1); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1},)" + R"("adComponentRenderURLs":{"https://foosub.test/":2,)" + R"("https://bazsub.test/":"4"},)" + R"("adComponentRenderUrls":{"https://foosub.test/":2,)" + R"("https://bazsub.test/":"4"}})", + ExtractScoringSignals(signals1.get(), kRenderUrl1, + kAdComponentRenderUrls1)); + + run_loop2.Run(); + EXPECT_FALSE(error_msg2); + ASSERT_TRUE(signals2); + EXPECT_EQ(R"({"renderURL":{"https://bar.test/":[2]},)" + R"("renderUrl":{"https://bar.test/":[2]},)" + R"("adComponentRenderURLs":{"https://barsub.test/":[3],)" + R"("https://bazsub.test/":"4"},)" + R"("adComponentRenderUrls":{"https://barsub.test/":[3],)" + R"("https://bazsub.test/":"4"}})", + ExtractScoringSignals(signals2.get(), kRenderUrl2, + kAdComponentRenderUrls2)); + + const GURL kRenderUrl3 = GURL("https://foo.test/"); + const std::vector<std::string> kAdComponentRenderUrls3{}; + + base::RunLoop run_loop3; + scoped_refptr<TrustedSignals::Result> signals3; + std::optional<std::string> error_msg3; + auto request3 = scoring_request_manager_.RequestScoringSignals( + kRenderUrl3, kAdComponentRenderUrls3, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals3, &error_msg3, + run_loop3.QuitClosure())); + + // Since we're not paused anymore, issuing happens at + // StartBatchedTrustedSignalsRequest call. + EXPECT_EQ(0, url_loader_factory_.NumPending()); + scoring_request_manager_.StartBatchedTrustedSignalsRequest(); + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse( + &url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Ffoo.test%2F"), + kBaseScoringJson); + run_loop3.Run(); + EXPECT_FALSE(error_msg3); + ASSERT_TRUE(signals3); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1}})", + ExtractScoringSignals(signals3.get(), kRenderUrl3, + kAdComponentRenderUrls3)); +} + // Make two requests, cancel both, then try to start a network request. No // requests should be made. Only test bidders, since sellers have no significant // differences in this path. @@ -1195,6 +1299,381 @@ EXPECT_EQ(R"({"key3":"3"})", ExtractBiddingSignals(signals3.get(), kKeys3)); } +TEST_F(TrustedSignalsRequestManagerTest, AutomaticallySendRequestsPause) { + const GURL kRenderUrl1 = GURL("https://foo.test/"); + const GURL kRenderUrl2 = GURL("https://bar.test/"); + + // Create a new scoring request manager with `automatically_send_requests` + // enabled. + TrustedSignalsRequestManager scoring_request_manager( + TrustedSignalsRequestManager::Type::kScoringSignals, &url_loader_factory_, + /*auction_network_events_handler=*/ + auction_network_events_handler_.CreateRemote(), + /*automatically_send_requests=*/true, + url::Origin::Create(GURL(kTopLevelOrigin)), trusted_signals_url_, + /*experiment_group_id=*/std::nullopt, + /*trusted_bidding_signals_slot_size_param=*/"", v8_helper_.get()); + scoring_request_manager.Pause(); + + // Create one Request. + base::RunLoop run_loop1; + scoped_refptr<TrustedSignals::Result> signals1; + std::optional<std::string> error_msg1; + auto request1 = scoring_request_manager.RequestScoringSignals( + kRenderUrl1, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals1, &error_msg1, + run_loop1.QuitClosure())); + + // Wait until just before the timer triggers. No network requests should be + // made. + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Nor after the timer, since this is paused. + task_environment_.FastForwardBy(kTinyTime); + ASSERT_EQ(0, url_loader_factory_.NumPending()); + + // Create another Request. + base::RunLoop run_loop2; + scoped_refptr<TrustedSignals::Result> signals2; + std::optional<std::string> error_msg2; + auto request2 = scoring_request_manager.RequestScoringSignals( + kRenderUrl2, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals2, &error_msg2, + run_loop2.QuitClosure())); + + // Wait until almost the timer time, and Resume. This means the next timer + // firing will be shortly after. + ASSERT_EQ(0, url_loader_factory_.NumPending()); + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Upon resume, the first two requests are issued. + scoring_request_manager.Resume(); + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse(&url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Fbar.test%" + "2F,https%3A%2F%2Ffoo.test%2F"), + kBaseScoringJson); + + run_loop1.Run(); + EXPECT_FALSE(error_msg1) << *error_msg1; + ASSERT_TRUE(signals1); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1}})", + ExtractScoringSignals(signals1.get(), kRenderUrl1, + /*ad_component_render_urls=*/{})); + + run_loop2.Run(); + EXPECT_FALSE(error_msg2) << *error_msg2; + ASSERT_TRUE(signals2); + EXPECT_EQ(R"({"renderURL":{"https://bar.test/":[2]},)" + R"("renderUrl":{"https://bar.test/":[2]}})", + ExtractScoringSignals(signals2.get(), kRenderUrl2, + /*ad_component_render_urls=*/{})); + + // Queue up a third request. + const std::vector<std::string> kAdComponentRenderUrls{"https://foosub.test/", + "https://bazsub.test/"}; + base::RunLoop run_loop3; + scoped_refptr<TrustedSignals::Result> signals3; + std::optional<std::string> error_msg3; + auto request3 = scoring_request_manager.RequestScoringSignals( + kRenderUrl1, kAdComponentRenderUrls, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals3, &error_msg3, + run_loop3.QuitClosure())); + + // Not issued yet. + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Going ahead by kTinyTime isn't enough either; the timer is started on first + // post-Resume request, not kept through the pause period. + task_environment_.FastForwardBy(kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime); + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + // Complete the request. + AddJsonResponse(&url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Ffoo.test%" + "2F&adComponentRenderUrls=https%3A%2F%2Fbazsub.test%2F," + "https%3A%2F%2Ffoosub.test%2F"), + kBaseScoringJson); + run_loop3.Run(); + EXPECT_FALSE(error_msg3) << *error_msg3; + ASSERT_TRUE(signals3); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1},)" + R"("adComponentRenderURLs":{"https://foosub.test/":2,)" + R"("https://bazsub.test/":"4"},)" + R"("adComponentRenderUrls":{"https://foosub.test/":2,)" + R"("https://bazsub.test/":"4"}})", + ExtractScoringSignals(signals3.get(), kRenderUrl1, + kAdComponentRenderUrls)); +} + +TEST_F(TrustedSignalsRequestManagerTest, AutomaticallySendRequestsLatePause) { + const GURL kRenderUrl1 = GURL("https://foo.test/"); + const GURL kRenderUrl2 = GURL("https://bar.test/"); + + // Create a new scoring request manager with `automatically_send_requests` + // enabled. + TrustedSignalsRequestManager scoring_request_manager( + TrustedSignalsRequestManager::Type::kScoringSignals, &url_loader_factory_, + /*auction_network_events_handler=*/ + auction_network_events_handler_.CreateRemote(), + /*automatically_send_requests=*/true, + url::Origin::Create(GURL(kTopLevelOrigin)), trusted_signals_url_, + /*experiment_group_id=*/std::nullopt, + /*trusted_bidding_signals_slot_size_param=*/"", v8_helper_.get()); + + // Create one Request. + base::RunLoop run_loop1; + scoped_refptr<TrustedSignals::Result> signals1; + std::optional<std::string> error_msg1; + auto request1 = scoring_request_manager.RequestScoringSignals( + kRenderUrl1, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals1, &error_msg1, + run_loop1.QuitClosure())); + + // Wait until a bit before the timer triggers. No network requests should be + // made. + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime - kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Pause and resume at this point. + scoring_request_manager.Pause(); + scoring_request_manager.Resume(); + + // Nothing is issued still, since we haven't gotten to batch end. + ASSERT_EQ(0, url_loader_factory_.NumPending()); + + // Not yet. + task_environment_.FastForwardBy(kTinyTime); + ASSERT_EQ(0, url_loader_factory_.NumPending()); + + // Create another Request. + base::RunLoop run_loop2; + scoped_refptr<TrustedSignals::Result> signals2; + std::optional<std::string> error_msg2; + auto request2 = scoring_request_manager.RequestScoringSignals( + kRenderUrl2, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals2, &error_msg2, + run_loop2.QuitClosure())); + + // Now it's up to timer time. + task_environment_.FastForwardBy(kTinyTime); + + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse(&url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Fbar.test%" + "2F,https%3A%2F%2Ffoo.test%2F"), + kBaseScoringJson); + + run_loop1.Run(); + EXPECT_FALSE(error_msg1) << *error_msg1; + ASSERT_TRUE(signals1); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1}})", + ExtractScoringSignals(signals1.get(), kRenderUrl1, + /*ad_component_render_urls=*/{})); + + run_loop2.Run(); + EXPECT_FALSE(error_msg2) << *error_msg2; + ASSERT_TRUE(signals2); + EXPECT_EQ(R"({"renderURL":{"https://bar.test/":[2]},)" + R"("renderUrl":{"https://bar.test/":[2]}})", + ExtractScoringSignals(signals2.get(), kRenderUrl2, + /*ad_component_render_urls=*/{})); +} + +TEST_F(TrustedSignalsRequestManagerTest, AutomaticallySendRequestsEarlyResume) { + const GURL kRenderUrl1 = GURL("https://foo.test/"); + const GURL kRenderUrl2 = GURL("https://bar.test/"); + + // Create a new scoring request manager with `automatically_send_requests` + // enabled. + TrustedSignalsRequestManager scoring_request_manager( + TrustedSignalsRequestManager::Type::kScoringSignals, &url_loader_factory_, + /*auction_network_events_handler=*/ + auction_network_events_handler_.CreateRemote(), + /*automatically_send_requests=*/true, + url::Origin::Create(GURL(kTopLevelOrigin)), trusted_signals_url_, + /*experiment_group_id=*/std::nullopt, + /*trusted_bidding_signals_slot_size_param=*/"", v8_helper_.get()); + scoring_request_manager.Pause(); + + // Create one Request. + base::RunLoop run_loop1; + scoped_refptr<TrustedSignals::Result> signals1; + std::optional<std::string> error_msg1; + auto request1 = scoring_request_manager.RequestScoringSignals( + kRenderUrl1, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals1, &error_msg1, + run_loop1.QuitClosure())); + + // Wait until a bit before the timer triggers. No network requests should be + // made. + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime - kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + scoring_request_manager.Resume(); + + // Nothing is issued still, since we haven't gotten to batch end. + ASSERT_EQ(0, url_loader_factory_.NumPending()); + + // Not yet. + task_environment_.FastForwardBy(kTinyTime); + ASSERT_EQ(0, url_loader_factory_.NumPending()); + + // Create another Request. + base::RunLoop run_loop2; + scoped_refptr<TrustedSignals::Result> signals2; + std::optional<std::string> error_msg2; + auto request2 = scoring_request_manager.RequestScoringSignals( + kRenderUrl2, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals2, &error_msg2, + run_loop2.QuitClosure())); + + // Now it's up to timer time. + task_environment_.FastForwardBy(kTinyTime); + + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse(&url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Fbar.test%" + "2F,https%3A%2F%2Ffoo.test%2F"), + kBaseScoringJson); + + run_loop1.Run(); + EXPECT_FALSE(error_msg1) << *error_msg1; + ASSERT_TRUE(signals1); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1}})", + ExtractScoringSignals(signals1.get(), kRenderUrl1, + /*ad_component_render_urls=*/{})); + + run_loop2.Run(); + EXPECT_FALSE(error_msg2) << *error_msg2; + ASSERT_TRUE(signals2); + EXPECT_EQ(R"({"renderURL":{"https://bar.test/":[2]},)" + R"("renderUrl":{"https://bar.test/":[2]}})", + ExtractScoringSignals(signals2.get(), kRenderUrl2, + /*ad_component_render_urls=*/{})); +} + +TEST_F(TrustedSignalsRequestManagerTest, + AutomaticallySendRequestsPauseWithExplicitFlush) { + const GURL kRenderUrl1 = GURL("https://foo.test/"); + const GURL kRenderUrl2 = GURL("https://bar.test/"); + + // Create a new scoring request manager with `automatically_send_requests` + // enabled. + TrustedSignalsRequestManager scoring_request_manager( + TrustedSignalsRequestManager::Type::kScoringSignals, &url_loader_factory_, + /*auction_network_events_handler=*/ + auction_network_events_handler_.CreateRemote(), + /*automatically_send_requests=*/true, + url::Origin::Create(GURL(kTopLevelOrigin)), trusted_signals_url_, + /*experiment_group_id=*/std::nullopt, + /*trusted_bidding_signals_slot_size_param=*/"", v8_helper_.get()); + + // Create one Request. + base::RunLoop run_loop1; + scoped_refptr<TrustedSignals::Result> signals1; + std::optional<std::string> error_msg1; + auto request1 = scoring_request_manager.RequestScoringSignals( + kRenderUrl1, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals1, &error_msg1, + run_loop1.QuitClosure())); + + // Pause before it gets chance to issue. + scoring_request_manager.Pause(); + + // Explicitly ask for a send; still doesn't send. + scoring_request_manager.StartBatchedTrustedSignalsRequest(); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Wait until just before the timer triggers. No network requests should be + // made. + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + scoring_request_manager.Resume(); + + // The request got sent now. + ASSERT_EQ(1, url_loader_factory_.NumPending()); + AddJsonResponse( + &url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Ffoo.test%2F"), + kBaseScoringJson); + + run_loop1.Run(); + EXPECT_FALSE(error_msg1) << *error_msg1; + ASSERT_TRUE(signals1); + EXPECT_EQ(R"({"renderURL":{"https://foo.test/":1},)" + R"("renderUrl":{"https://foo.test/":1}})", + ExtractScoringSignals(signals1.get(), kRenderUrl1, + /*ad_component_render_urls=*/{})); + + // Create another Request. + base::RunLoop run_loop2; + scoped_refptr<TrustedSignals::Result> signals2; + std::optional<std::string> error_msg2; + auto request2 = scoring_request_manager.RequestScoringSignals( + kRenderUrl2, /*ad_component_render_urls=*/{}, + /*max_trusted_scoring_signals_url_length=*/0, + base::BindOnce(&LoadSignalsCallback, &signals2, &error_msg2, + run_loop2.QuitClosure())); + + // Up to timer time from initial request, it's still not sent. + task_environment_.FastForwardBy(kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + + // Need to get to timer time after resume. + task_environment_.FastForwardBy(TrustedSignalsRequestManager::kAutoSendDelay - + kTinyTime - kTinyTime); + EXPECT_EQ(0, url_loader_factory_.NumPending()); + task_environment_.FastForwardBy(kTinyTime); + EXPECT_EQ(1, url_loader_factory_.NumPending()); + + AddJsonResponse( + &url_loader_factory_, + GURL("https://url.test/" + "?hostname=publisher&renderUrls=https%3A%2F%2Fbar.test%2F"), + kBaseScoringJson); + + run_loop2.Run(); + EXPECT_FALSE(error_msg2) << *error_msg2; + ASSERT_TRUE(signals2); + EXPECT_EQ(R"({"renderURL":{"https://bar.test/":[2]},)" + R"("renderUrl":{"https://bar.test/":[2]}})", + ExtractScoringSignals(signals2.get(), kRenderUrl2, + /*ad_component_render_urls=*/{})); +} + TEST_F(TrustedSignalsRequestManagerTest, AutomaticallySendRequestsCancelAllRequestsRestartsTimer) { const std::vector<std::string> kKeys1{"key1"};
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc index 2711127a..22efadf96 100644 --- a/content/test/content_browser_test_utils_internal.cc +++ b/content/test/content_browser_test_utils_internal.cc
@@ -582,8 +582,7 @@ RenderFrameHostImpl* frame_host) : frame_host_(frame_host) { #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) - web_contents_ = web_contents; - web_contents_->set_show_popup_menu_callback_for_testing(base::BindOnce( + frame_host->set_show_popup_menu_callback_for_testing(base::BindOnce( &ShowPopupWidgetWaiter::ShowPopupMenu, base::Unretained(this))); #endif frame_host_->SetCreateNewPopupCallbackForTesting(base::BindRepeating( @@ -605,7 +604,7 @@ void ShowPopupWidgetWaiter::Stop() { #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) - web_contents_->set_show_popup_menu_callback_for_testing(base::NullCallback()); + frame_host_->set_show_popup_menu_callback_for_testing(base::NullCallback()); #endif frame_host_->SetCreateNewPopupCallbackForTesting(base::NullCallback()); frame_host_ = nullptr;
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h index d406016..e9663dd 100644 --- a/content/test/content_browser_test_utils_internal.h +++ b/content/test/content_browser_test_utils_internal.h
@@ -326,9 +326,6 @@ int32_t routing_id_ = MSG_ROUTING_NONE; int32_t process_id_ = 0; raw_ptr<RenderFrameHostImpl> frame_host_; -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) - raw_ptr<WebContentsImpl> web_contents_; -#endif }; // This observer waits until WebContentsObserver::OnRendererUnresponsive
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index a2318ee2b..8317186 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -1005,6 +1005,7 @@ crbug.com/332743717 [ mac angle-metal ] conformance2/query/occlusion-query-scissor.html [ Failure ] crbug.com/332743717 [ mac intel angle-opengl ] conformance2/canvas/drawingbuffer-storage-test.html [ Failure ] crbug.com/332743717 [ chromeos chromeos-board-amd64-generic ] conformance2/canvas/drawingbuffer-storage-test.html [ Failure ] +crbug.com/332743717 [ chromeos chromeos-board-octopus ] conformance2/canvas/drawingbuffer-storage-test.html [ Failure ] crbug.com/332743717 [ android android-pixel-2 ] conformance2/canvas/drawingbuffer-storage-test.html [ Failure ] crbug.com/335203259 [ android android-pixel-2 ] conformance2/wasm/bufferdata-16gb-wasm-memory.html [ Failure ] crbug.com/335203259 [ android android-pixel-2 ] conformance2/wasm/bufferdata-4gb-wasm-memory.html [ Failure ]
diff --git a/content/web_test/renderer/web_ax_object_proxy.cc b/content/web_test/renderer/web_ax_object_proxy.cc index 5088526..b1c92247 100644 --- a/content/web_test/renderer/web_ax_object_proxy.cc +++ b/content/web_test/renderer/web_ax_object_proxy.cc
@@ -969,7 +969,7 @@ if (!UpdateLayout()) { return false; } - return accessibility_object_.AccessibilityIsIgnored(); + return accessibility_object_.IsIgnored(); } v8::Local<v8::Object> WebAXObjectProxy::ActiveDescendant() {
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index d0986f4..0ec35f0c 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -167,8 +167,10 @@ "enclave/verify/claim.h", "enclave/verify/endorsement.cc", "enclave/verify/endorsement.h", - "enclave/verify/utils.h", + "enclave/verify/hash.cc", + "enclave/verify/hash.h", "enclave/verify/utils.cc", + "enclave/verify/utils.h", "enclave/verify/verify.h", "fido_authenticator.cc", "fido_authenticator.h",
diff --git a/device/fido/enclave/verify/claim.cc b/device/fido/enclave/verify/claim.cc index 4bf28fe..c17dd4e 100644 --- a/device/fido/enclave/verify/claim.cc +++ b/device/fido/enclave/verify/claim.cc
@@ -14,7 +14,7 @@ ClaimEvidence::ClaimEvidence() = default; ClaimEvidence::ClaimEvidence(std::optional<std::string> role, std::string uri, - std::vector<uint8_t> digest) + std::map<std::string, std::string> digest) : role(std::move(role)), uri(std::move(uri)), digest(std::move(digest)) {} ClaimEvidence::~ClaimEvidence() = default;
diff --git a/device/fido/enclave/verify/claim.h b/device/fido/enclave/verify/claim.h index 5e1d3a86..7d4aa215 100644 --- a/device/fido/enclave/verify/claim.h +++ b/device/fido/enclave/verify/claim.h
@@ -40,13 +40,13 @@ struct ClaimEvidence { ClaimEvidence(std::optional<std::string> role, std::string uri, - std::vector<uint8_t> digest); + std::map<std::string, std::string> digest); ClaimEvidence(); ~ClaimEvidence(); std::optional<std::string> role; std::string uri; - std::vector<uint8_t> digest; + std::map<std::string, std::string> digest; }; // Validity time range of an issued claim.
diff --git a/device/fido/enclave/verify/endorsement.h b/device/fido/enclave/verify/endorsement.h index e912877..eef2e7f 100644 --- a/device/fido/enclave/verify/endorsement.h +++ b/device/fido/enclave/verify/endorsement.h
@@ -11,6 +11,7 @@ #include "base/containers/span.h" #include "base/time/time.h" #include "device/fido/enclave/verify/claim.h" +#include "device/fido/enclave/verify/hash.h" namespace device::enclave { @@ -18,7 +19,7 @@ // ready. // Compares the digest contained in the endorsement against the given one. bool VerifyBinaryDigest(base::span<const uint8_t> endorsement, - base::span<const uint8_t> expected); + const Hash& expected); // Verifies the binary endorsement against log entry and public keys. bool VerifyBinaryEndorsement(base::Time now,
diff --git a/device/fido/enclave/verify/hash.cc b/device/fido/enclave/verify/hash.cc new file mode 100644 index 0000000..b0104af --- /dev/null +++ b/device/fido/enclave/verify/hash.cc
@@ -0,0 +1,16 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/enclave/verify/hash.h" + +#include <vector> + +namespace device::enclave { + +Hash::Hash(std::vector<uint8_t> bytes, HashType hash_type) + : bytes(std::move(bytes)), hash_type(hash_type) {} +Hash::Hash() = default; +Hash::~Hash() = default; + +} // namespace device::enclave
diff --git a/device/fido/enclave/verify/hash.h b/device/fido/enclave/verify/hash.h new file mode 100644 index 0000000..59bf7f7 --- /dev/null +++ b/device/fido/enclave/verify/hash.h
@@ -0,0 +1,28 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_FIDO_ENCLAVE_VERIFY_HASH_H_ +#define DEVICE_FIDO_ENCLAVE_VERIFY_HASH_H_ + +#include <cstdint> +#include <vector> + +namespace device::enclave { + +enum HashType { + kSHA256, +}; + +struct Hash { + Hash(std::vector<uint8_t> bytes, HashType hash_type); + Hash(); + ~Hash(); + + std::vector<uint8_t> bytes; + HashType hash_type = kSHA256; +}; + +} // namespace device::enclave + +#endif // DEVICE_FIDO_ENCLAVE_VERIFY_HASH_H_
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md index ce82347..02f80a4 100644 --- a/docs/threading_and_tasks.md +++ b/docs/threading_and_tasks.md
@@ -956,7 +956,7 @@ ``` Please be SURE your task is reentrant (nestable) and all global variables -are stable and accessible before before using +are stable and accessible before using CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop. ## APIs for general use
diff --git a/docs/website b/docs/website index fe917d7..c50bcc0 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit fe917d70bbd8c9902b8d1fe751958a6cc55c86b4 +Subproject commit c50bcc04d18f45a37e8b7aca67e712d20bf145c2
diff --git a/extensions/browser/api/audio/audio_apitest_chromeos.cc b/extensions/browser/api/audio/audio_apitest_chromeos.cc index 0b701df..7b9fc557c 100644 --- a/extensions/browser/api/audio/audio_apitest_chromeos.cc +++ b/extensions/browser/api/audio/audio_apitest_chromeos.cc
@@ -11,6 +11,7 @@ #include "base/run_loop.h" #include "build/build_config.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" +#include "chromeos/ash/components/audio/device_activate_type.h" #include "chromeos/ash/components/dbus/audio/fake_cras_audio_client.h" #include "extensions/common/features/feature_session_type.h" #include "extensions/shell/test/shell_apitest.h" @@ -201,7 +202,7 @@ // Set the jabra mic to be the active input device. AudioDevice jabra_mic(CreateAudioNode(kJabraMic1, 2)); audio_handler()->SwitchToDevice(jabra_mic, true, - CrasAudioHandler::ACTIVATE_BY_USER); + ash::DeviceActivateType::kActivateByUser); EXPECT_EQ(kJabraMic1.id, audio_handler()->GetPrimaryActiveInputNode()); // Un-mute the input.
diff --git a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc index 8b7064d..119de3df 100644 --- a/extensions/browser/api/printer_provider/printer_provider_internal_api.cc +++ b/extensions/browser/api/printer_provider/printer_provider_internal_api.cc
@@ -189,9 +189,7 @@ // |job->document_bytes| are passed to the callback to make sure the ref // counted memory does not go away before the memory backed blob is created. browser_context()->CreateMemoryBackedBlob( - base::make_span(job->document_bytes->front(), - job->document_bytes->size()), - job->content_type, + base::span(*job->document_bytes), job->content_type, base::BindOnce(&PrinterProviderInternalGetPrintDataFunction::OnBlob, this, job->document_bytes)); return RespondLater();
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc index a9c432ee..1d5ab28c 100644 --- a/extensions/common/switches.cc +++ b/extensions/common/switches.cc
@@ -6,97 +6,41 @@ #include "build/chromeos_buildflags.h" -namespace extensions { +namespace extensions::switches { -namespace switches { - -// Allows non-https URL for background_page for hosted apps. const char kAllowHTTPBackgroundPage[] = "allow-http-background-page"; - -// Allows the browser to load extensions that lack a modern manifest when that -// would otherwise be forbidden. const char kAllowLegacyExtensionManifests[] = "allow-legacy-extension-manifests"; - -// Adds the given extension ID to all the permission allowlists. const char kAllowlistedExtensionID[] = "allowlisted-extension-id"; - -// Enables extension options to be embedded in chrome://extensions rather than -// a new tab. const char kEmbeddedExtensionOptions[] = "embedded-extension-options"; - -// Enable BLE Advertising in apps. const char kEnableBLEAdvertising[] = "enable-ble-advertising-in-apps"; - -// Enables extension APIs that are in development. const char kEnableExperimentalExtensionApis[] = "enable-experimental-extension-apis"; - -// Disable checking for user opt-in for extensions that want to inject script -// into file URLs (ie, always allow it). This is used during automated testing. const char kDisableExtensionsFileAccessCheck[] = "disable-extensions-file-access-check"; - -// Disable the net::URLRequestThrottlerManager functionality for -// requests originating from extensions. const char kDisableExtensionsHttpThrottling[] = "disable-extensions-http-throttling"; - -// Marks a renderer as extension process. const char kExtensionProcess[] = "extension-process"; - -// Enables extensions running scripts on chrome:// URLs. -// Extensions still need to explicitly request access to chrome:// URLs in the -// manifest. const char kExtensionsOnChromeURLs[] = "extensions-on-chrome-urls"; - -// Whether to force developer mode extensions highlighting. const char kForceDevModeHighlighting[] = "force-dev-mode-highlighting"; - -// Whether to disable app content verification when testing changes locally on -// Chromebox for Meetings hardware. const char kDisableAppContentVerification[] = "disable-app-content-verification"; - -// Comma-separated list of paths to apps to load at startup. The first app in -// the list will be launched. const char kLoadApps[] = "load-apps"; - -// Comma-separated list of paths to extensions to load at startup. const char kLoadExtension[] = "load-extension"; #if BUILDFLAG(IS_CHROMEOS_ASH) -// Path to the unpacked test extension to load into the signin profile. The ID -// extension loaded must match kTestSigninProfileExtensionId. const char kLoadSigninProfileTestExtension[] = "load-signin-profile-test-extension"; - -// Path to the unpacked test extension to load into guest mode. The extension ID -// must match kGuestModeTestExtensionId. const char kLoadGuestModeTestExtension[] = "load-guest-mode-test-extension"; #endif -// Allows the use of the `testing` reason in offscreen documents. const char kOffscreenDocumentTesting[] = "offscreen-document-testing"; - -// Set the parameters for ExtensionURLLoaderThrottleBrowserTest. const char kSetExtensionThrottleTestParams[] = "set-extension-throttle-test-params"; - -// Makes component extensions appear in chrome://settings/extensions. const char kShowComponentExtensionOptions[] = "show-component-extension-options"; - -// Pass launch source to platform apps. const char kTraceAppSource[] = "enable-trace-app-source"; - -// Enable package hash check: the .crx file sha256 hash sum should be equal to -// the one received from update manifest. const char kEnableCrxHashCheck[] = "enable-crx-hash-check"; - -// Mute extension errors while working with new manifest version. const char kAllowFutureManifestVersion[] = "allow-future-manifest-version"; -} // namespace switches - -} // namespace extensions +} // namespace extensions::switches
diff --git a/extensions/common/switches.h b/extensions/common/switches.h index 9dffc5e862..6b29d08 100644 --- a/extensions/common/switches.h +++ b/extensions/common/switches.h
@@ -7,39 +7,87 @@ #include "build/chromeos_buildflags.h" -// All switches in alphabetical order. The switches should be documented -// alongside the definition of their values in the .cc file. -namespace extensions { +namespace extensions::switches { -namespace switches { - +// Allows non-https URL for background_page for hosted apps. extern const char kAllowHTTPBackgroundPage[]; + +// Allows the browser to load extensions that lack a modern manifest when that +// would otherwise be forbidden. extern const char kAllowLegacyExtensionManifests[]; + +// Adds the given extension ID to all the permission allowlists. extern const char kAllowlistedExtensionID[]; + +// Whether to disable app content verification when testing changes locally on +// Chromebox for Meetings hardware. extern const char kDisableAppContentVerification[]; + +// Disable checking for user opt-in for extensions that want to inject script +// into file URLs (ie, always allow it). This is used during automated testing. extern const char kDisableExtensionsFileAccessCheck[]; + +// Disable the net::URLRequestThrottlerManager functionality for +// requests originating from extensions. extern const char kDisableExtensionsHttpThrottling[]; + +// Enables extension options to be embedded in chrome://extensions rather than +// a new tab. extern const char kEmbeddedExtensionOptions[]; + +// Enables extension APIs that are in development. extern const char kEnableExperimentalExtensionApis[]; + +// Enable BLE Advertising in apps. extern const char kEnableBLEAdvertising[]; + +// Marks a renderer as extension process. extern const char kExtensionProcess[]; + +// Enables extensions running scripts on chrome:// URLs. +// Extensions still need to explicitly request access to chrome:// URLs in the +// manifest. extern const char kExtensionsOnChromeURLs[]; + +// Whether to force developer mode extensions highlighting. extern const char kForceDevModeHighlighting[]; + +// Comma-separated list of paths to apps to load at startup. The first app in +// the list will be launched. extern const char kLoadApps[]; + +// Comma-separated list of paths to extensions to load at startup. extern const char kLoadExtension[]; + #if BUILDFLAG(IS_CHROMEOS_ASH) +// Path to the unpacked test extension to load into the signin profile. The ID +// extension loaded must match kTestSigninProfileExtensionId. extern const char kLoadSigninProfileTestExtension[]; + +// Path to the unpacked test extension to load into guest mode. The extension ID +// must match kGuestModeTestExtensionId. extern const char kLoadGuestModeTestExtension[]; #endif + +// Allows the use of the `testing` reason in offscreen documents. extern const char kOffscreenDocumentTesting[]; + +// Set the parameters for ExtensionURLLoaderThrottleBrowserTest. extern const char kSetExtensionThrottleTestParams[]; + +// Makes component extensions appear in chrome://settings/extensions. extern const char kShowComponentExtensionOptions[]; + +// Pass launch source to platform apps. extern const char kTraceAppSource[]; + +// Enable package hash check: the .crx file sha256 hash sum should be equal to +// the one received from update manifest. extern const char kEnableCrxHashCheck[]; + +// Mute extension errors while working with new manifest version. extern const char kAllowFutureManifestVersion[]; -} // namespace switches - -} // namespace extensions +} // namespace extensions::switches #endif // EXTENSIONS_COMMON_SWITCHES_H_
diff --git a/extensions/shell/browser/shell_audio_controller_chromeos.cc b/extensions/shell/browser/shell_audio_controller_chromeos.cc index a4c947e..707ab99d1 100644 --- a/extensions/shell/browser/shell_audio_controller_chromeos.cc +++ b/extensions/shell/browser/shell_audio_controller_chromeos.cc
@@ -62,13 +62,15 @@ const AudioDevice* device = GetDevice(devices, best_input); DCHECK(device); VLOG(1) << "Activating input device: " << device->ToString(); - handler->SwitchToDevice(*device, true, CrasAudioHandler::ACTIVATE_BY_USER); + handler->SwitchToDevice(*device, true, + ash::DeviceActivateType::kActivateByUser); } if (best_output && best_output != handler->GetPrimaryActiveOutputNode()) { const AudioDevice* device = GetDevice(devices, best_output); DCHECK(device); VLOG(1) << "Activating output device: " << device->ToString(); - handler->SwitchToDevice(*device, true, CrasAudioHandler::ACTIVATE_BY_USER); + handler->SwitchToDevice(*device, true, + ash::DeviceActivateType::kActivateByUser); } }
diff --git a/gpu/command_buffer/client/client_shared_image.cc b/gpu/command_buffer/client/client_shared_image.cc index ef7d92e1..b1f7f885 100644 --- a/gpu/command_buffer/client/client_shared_image.cc +++ b/gpu/command_buffer/client/client_shared_image.cc
@@ -121,8 +121,8 @@ "UseUniversalGetTextureTargetFunction", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kDestroySharedImageAutomatically, - "DestroySharedImageAutomatically", +BASE_FEATURE(kEnableAutomaticSharedImageManagement, + "EnableAutomaticSharedImageManagement", base::FEATURE_ENABLED_BY_DEFAULT); ClientSharedImage::ScopedMapping::ScopedMapping() = default; @@ -278,7 +278,7 @@ return; } - if (base::FeatureList::IsEnabled(kDestroySharedImageAutomatically) || + if (base::FeatureList::IsEnabled(kEnableAutomaticSharedImageManagement) || marked_for_destruction_) { auto sii = sii_holder_->Get(); if (sii) {
diff --git a/gpu/command_buffer/client/client_shared_image.h b/gpu/command_buffer/client/client_shared_image.h index c7063464..c0811d9 100644 --- a/gpu/command_buffer/client/client_shared_image.h +++ b/gpu/command_buffer/client/client_shared_image.h
@@ -32,7 +32,7 @@ // Controls whether SharedImageInterface::DestroySharedImage() should be called // in ClientSharedImage's destructor if the shared image has not been marked // for destruction. -GPU_EXPORT BASE_DECLARE_FEATURE(kDestroySharedImageAutomatically); +GPU_EXPORT BASE_DECLARE_FEATURE(kEnableAutomaticSharedImageManagement); struct ExportedSharedImage;
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index b154362..6e8cc80 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -80,7 +80,7 @@ void* memory(size_t plane) override { DCHECK(mapped_); DCHECK_LT(plane, gfx::NumberOfPlanesForLinearBufferFormat(format_)); - return reinterpret_cast<uint8_t*>(&bytes_->data().front()) + + return bytes_->as_vector().data() + gfx::BufferOffsetForBufferFormat(size_, format_, plane); } void Unmap() override {
diff --git a/infra/archive_config/linux-archive-rel.json b/infra/archive_config/linux-archive-rel.json index d0ac9ae..c8c8af0 100644 --- a/infra/archive_config/linux-archive-rel.json +++ b/infra/archive_config/linux-archive-rel.json
@@ -104,6 +104,7 @@ "gen/ui/gfx/geometry/mojom/geometry.mojom.m.js", "gen/device/gamepad/public/mojom/gamepad.mojom.m.js", "gen/device/vr/public/mojom/vr_service.mojom.m.js", + "gen/device/vr/public/mojom/xr_session.mojom.m.js", "gen/url/mojom/url.mojom.m.js", "gen/third_party/blink/public/mojom/usb/web_usb_service.mojom.m.js", "gen/device/bluetooth/public/mojom/uuid.mojom.m.js",
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl index 2f2279e..07178d3 100644 --- a/infra/config/generated/testing/test_suites.pyl +++ b/infra/config/generated/testing/test_suites.pyl
@@ -4140,6 +4140,12 @@ '--test-launcher-filter-file=testing/buildbot/filters/ios.compositor_unittests.filter', ], }, + 'content_browsertests': { + 'args': [ + '--test-launcher-bot-mode', + '--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter', + ], + }, 'content_unittests': { 'args': [ '--test-launcher-bot-mode', @@ -4419,7 +4425,6 @@ 'browser_tests_require_lacros': { 'test': 'browser_tests', 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter', '--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome', ], 'swarming': { @@ -4451,7 +4456,6 @@ 'ci_only': True, }, 'ash_unittests': { - 'ci_only': True, 'swarming': { 'shards': 5, },
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index 87b049c..a1e33cc 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -267,32 +267,32 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 126.0.6425.0', + 'description': 'Run with ash-chrome version 126.0.6426.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v126.0.6425.0', - 'revision': 'version:126.0.6425.0', + 'location': 'lacros_version_skew_tests_v126.0.6426.0', + 'revision': 'version:126.0.6426.0', }, ], }, }, 'LACROS_VERSION_SKEW_DEV': { 'identifier': 'Lacros version skew testing ash dev', - 'description': 'Run with ash-chrome version 125.0.6411.0', + 'description': 'Run with ash-chrome version 125.0.6422.5', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6411.0', - 'revision': 'version:125.0.6411.0', + 'location': 'lacros_version_skew_tests_v125.0.6422.5', + 'revision': 'version:125.0.6422.5', }, ], },
diff --git a/infra/config/targets/basic_suites.star b/infra/config/targets/basic_suites.star index d781007..6477e999 100644 --- a/infra/config/targets/basic_suites.star +++ b/infra/config/targets/basic_suites.star
@@ -3796,6 +3796,12 @@ "--test-launcher-filter-file=testing/buildbot/filters/ios.compositor_unittests.filter", ], ), + "content_browsertests": targets.legacy_test_config( + args = [ + "--test-launcher-bot-mode", + "--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter", + ], + ), "content_unittests": targets.legacy_test_config( args = [ "--test-launcher-bot-mode", @@ -4139,9 +4145,6 @@ ci_only = True, ), "ash_unittests": targets.legacy_test_config( - # TODO(crbug.com/333572800): remove "ci_only = True" when issue is - # fixed - ci_only = True, swarming = targets.swarming( shards = 5, ),
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json index 1474b80..ed564bda 100644 --- a/infra/config/targets/lacros-version-skew-variants.json +++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,32 +1,32 @@ { "LACROS_VERSION_SKEW_CANARY": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "identifier": "Lacros version skew testing ash canary", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ] } }, "LACROS_VERSION_SKEW_DEV": { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "identifier": "Lacros version skew testing ash dev", "swarming": { "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ] }
diff --git a/infra/config/targets/tests.star b/infra/config/targets/tests.star index 3d89a2a52..aa7816b 100644 --- a/infra/config/targets/tests.star +++ b/infra/config/targets/tests.star
@@ -342,7 +342,6 @@ targets.tests.gtest_test( name = "browser_tests_require_lacros", args = [ - "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter", "--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome", ], binary = "browser_tests",
diff --git a/internal b/internal index f5dce23..12652b9 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit f5dce23de2e76a39aeabd5418dfcda30b6c8106a +Subproject commit 12652b92c8a9ff5daaf5f8d692569028e59cda05
diff --git a/ios/chrome/browser/favicon/model/favicon_loader_unittest.mm b/ios/chrome/browser/favicon/model/favicon_loader_unittest.mm index 6e819d6a..4fe2af3 100644 --- a/ios/chrome/browser/favicon/model/favicon_loader_unittest.mm +++ b/ios/chrome/browser/favicon/model/favicon_loader_unittest.mm
@@ -56,10 +56,10 @@ bitmapResult.expired = false; // Create bitmap. - scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); + auto data = base::MakeRefCounted<base::RefCountedBytes>(); SkBitmap bitmap; bitmap.allocN32Pixels(30, 30); - gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->data()); + gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->as_vector()); bitmapResult.bitmap_data = data; favicon_base::LargeIconResult result(bitmapResult);
diff --git a/ios/chrome/browser/favicon/model/large_icon_cache_unittest.cc b/ios/chrome/browser/favicon/model/large_icon_cache_unittest.cc index 7b80850..23cb159e 100644 --- a/ios/chrome/browser/favicon/model/large_icon_cache_unittest.cc +++ b/ios/chrome/browser/favicon/model/large_icon_cache_unittest.cc
@@ -27,7 +27,7 @@ // Create bitmap and fill with `color`. scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); gfx::PNGCodec::EncodeBGRASkBitmap(gfx::test::CreateBitmap(w, h, color), false, - &data->data()); + &data->as_vector()); result.bitmap_data = data; result.pixel_size = gfx::Size(w, h);
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h index 5a6ad5f2..a00e315 100644 --- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
@@ -13,6 +13,7 @@ #import "base/memory/raw_ptr.h" #import "components/keyed_service/core/keyed_service.h" #import "components/sessions/core/live_tab_context.h" +#include "components/sessions/core/tab_restore_types.h" #import "ios/chrome/browser/shared/model/browser/browser_observer.h" #import "ios/chrome/browser/shared/model/browser/browser_user_data.h" @@ -60,27 +61,11 @@ const gfx::Rect GetRestoredBounds() const override; ui::WindowShowState GetRestoredState() const override; std::string GetWorkspace() const override; - sessions::LiveTab* AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) override; + sessions::LiveTab* AddRestoredTab(const sessions::tab_restore::Tab& tab, + int tab_index, + bool select) override; sessions::LiveTab* ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) override; + const sessions::tab_restore::Tab& tab) override; void CloseTab() override; private:
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm index 6779c26..da0ad48 100644 --- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
@@ -128,38 +128,23 @@ } sessions::LiveTab* LiveTabContextBrowserAgent::AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, + const sessions::tab_restore::Tab& tab, int tab_index, - int selected_navigation, - const std::string& extension_app_id, - std::optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data, - const SessionID* tab_id) { + bool select) { // TODO(crbug.com/661636): Handle tab-switch animation somehow... web_state_list_->InsertWebState( session_util::CreateWebStateWithNavigationEntries( - browser_state_, selected_navigation, navigations), + browser_state_, tab.normalized_navigation_index(), tab.navigations), WebStateList::InsertionParams::AtIndex(tab_index).Activate()); return nullptr; } sessions::LiveTab* LiveTabContextBrowserAgent::ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - std::optional<tab_groups::TabGroupId> group, - int selected_navigation, - const std::string& extension_app_id, - const sessions::tab_restore::PlatformSpecificTabData* tab_platform_data, - const sessions::SerializedUserAgentOverride& user_agent_override, - const std::map<std::string, std::string>& extra_data) { + const sessions::tab_restore::Tab& tab) { web_state_list_->ReplaceWebStateAt( web_state_list_->active_index(), session_util::CreateWebStateWithNavigationEntries( - browser_state_, selected_navigation, navigations)); + browser_state_, tab.normalized_navigation_index(), tab.navigations)); return nullptr; }
diff --git a/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.mm b/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.mm index e67c55d0..ac59b41 100644 --- a/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.mm +++ b/ios/chrome/browser/shared/coordinator/alert/alert_coordinator.mm
@@ -115,14 +115,17 @@ } - (void)stop { - if (_noInteractionAction) { - _noInteractionAction(); - _noInteractionAction = nil; - } + ProceduralBlock noInteractionAction = _noInteractionAction; + _noInteractionAction = nil; [[_alertController presentingViewController] dismissViewControllerAnimated:NO completion:nil]; [self alertDismissed]; + if (noInteractionAction) { + // This callback might deallocate `self`. Nothing should be done after + // calling `noInteractionAction()`. + noInteractionAction(); + } } #pragma mark - Property Implementation.
diff --git a/ios/chrome/browser/tabs/model/tab_helper_util.mm b/ios/chrome/browser/tabs/model/tab_helper_util.mm index 9059b181..f2a8ca9 100644 --- a/ios/chrome/browser/tabs/model/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/model/tab_helper_util.mm
@@ -275,9 +275,7 @@ ]); } - if (!base::FeatureList::IsEnabled(kEnableStartupImprovements)) { - InfobarBadgeTabHelper::GetOrCreateForWebState(web_state); - } + InfobarBadgeTabHelper::GetOrCreateForWebState(web_state); if (base::FeatureList::IsEnabled(kSharedHighlightingIOS)) { LinkToTextTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/ntp/feed_management/follow_management_mediator_unittest.mm b/ios/chrome/browser/ui/ntp/feed_management/follow_management_mediator_unittest.mm index 9ac2971..80bfe80 100644 --- a/ios/chrome/browser/ui/ntp/feed_management/follow_management_mediator_unittest.mm +++ b/ios/chrome/browser/ui/ntp/feed_management/follow_management_mediator_unittest.mm
@@ -56,7 +56,7 @@ scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); SkBitmap bitmap; bitmap.allocN32Pixels(30, 30); - gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->data()); + gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->as_vector()); bitmapResult.bitmap_data = data; favicon_base::LargeIconResult result(bitmapResult);
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm index 2b4f7b4..8c11dcd0 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_header_view.mm
@@ -456,6 +456,11 @@ percent = std::clamp<CGFloat>( animatingOffset / ntp_header::kAnimationDistance, 0, 1); } + if (!IsSplitToolbarMode(self)) { + // For ipad and landscape iphone, this makes the animation start slowly + // and accelerate especially towards the end. + percent = percent * percent; + } return percent; } @@ -710,11 +715,8 @@ // For non-split toolbar, the fake omnibox goes beneath the toolbar. if (!IsSplitToolbarMode(self)) { - // The animation should start when the primary toolbar is met, with an - // additional 1/4 height so the fake omnibox text appears to fade into the - // primary toolbar. - offset += content_suggestions::FakeOmniboxHeight() + - (content_suggestions::FakeOmniboxHeight() / 4); + // The animation should start when the primary toolbar is met. + offset += content_suggestions::FakeOmniboxHeight(); // iPads pin slightly earlier than landscape iPhones. if (IsRegularXRegularSizeClass(self)) {
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm index f65b505..0cb7455 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -1738,12 +1738,15 @@ // for Discover infinite feed. CGFloat minimumHeight = collectionViewHeight + headerHeight; if (!IsRegularXRegularSizeClass(self.collectionView)) { - CGFloat toolbarHeight = IsSplitToolbarMode(self.collectionView) - ? [self stickyOmniboxHeight] - : 0; - CGFloat additionalHeight = - toolbarHeight + self.collectionView.contentInset.bottom; - minimumHeight -= additionalHeight; + minimumHeight -= self.collectionView.contentInset.bottom; + if (IsSplitToolbarMode(self)) { + minimumHeight -= [self stickyOmniboxHeight]; + } else { + // Add in half of the margin between the fakebox and the rest of the + // content suggestions, to ensure there is enough height to fully + // finish the fakebox to omnibox transition. + minimumHeight += content_suggestions::HeaderBottomPadding() / 2; + } } return minimumHeight;
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/password_manager_view_controller_delegate.h index 34a9c53..f17f6aa6 100644 --- a/ios/chrome/browser/ui/settings/password/password_manager_view_controller_delegate.h +++ b/ios/chrome/browser/ui/settings/password/password_manager_view_controller_delegate.h
@@ -7,6 +7,8 @@ #import <Foundation/Foundation.h> +#include <vector> + namespace password_manager { class AffiliatedGroup; struct CredentialUIEntry;
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm index d0558996..41b98d0c 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/side_swipe/side_swipe_navigation_view.h" +#import <cmath> #import <numbers> #import "base/check.h"
diff --git a/ios/third_party/webkit/src b/ios/third_party/webkit/src index 59e9de6..f8c0fe7 160000 --- a/ios/third_party/webkit/src +++ b/ios/third_party/webkit/src
@@ -1 +1 @@ -Subproject commit 59e9de61b7b36507836fa8b098e8839d7d995b13 +Subproject commit f8c0fe750d94b7db23d193c0b1f31858c2537620
diff --git a/ios/web/public/test/web_task_environment.h b/ios/web/public/test/web_task_environment.h index 4fade0b..8377311 100644 --- a/ios/web/public/test/web_task_environment.h +++ b/ios/web/public/test/web_task_environment.h
@@ -30,13 +30,9 @@ // WebTaskEnvironment lives. The destructor of WebTaskEnvironment runs remaining // TestWebThreads tasks and remaining BLOCK_SHUTDOWN thread pool tasks. // -// Some tests using the IO thread expect a MessageLoopForIO. Passing IO_MAINLOOP -// will use a MessageLoopForIO for the main MessageLoop. Most of the time, this -// avoids needing to use a REAL_IO_THREAD. - -namespace base { -class MessageLoop; -} // namespace base +// Some tests using the IO thread expect a MessageLoopForIO. Passing +// MainThreadType::IO will use a MessageLoopForIO for the main MessageLoop. +// Most of the time, this avoids needing to use a IOThreadType::REAL_THREAD. namespace web { @@ -44,15 +40,6 @@ class WebTaskEnvironment : public base::test::TaskEnvironment { public: - // Used to specify the type of MessageLoop that backs the UI thread, and - // which of the named WebThreads should be backed by a real - // threads. The UI thread is always the main thread in a unit test. - enum Options { - DEFAULT = 0, - IO_MAINLOOP = 1 << 0, - REAL_IO_THREAD = 1 << 1, - }; - // This type will determine which events will be pumped by the main // thread. Note that the default is different from TaskEnvironment. enum class MainThreadType { @@ -90,11 +77,6 @@ IOThreadType::DEFAULT>(traits...), base::trait_helpers::NotATraitTag()) {} - explicit WebTaskEnvironment( - int options = Options::DEFAULT, - base::test::TaskEnvironment::TimeSource time_source = - base::test::TaskEnvironment::TimeSource::DEFAULT); - WebTaskEnvironment(const WebTaskEnvironment&) = delete; WebTaskEnvironment& operator=(const WebTaskEnvironment&) = delete;
diff --git a/ios/web/test/web_task_environment.cc b/ios/web/test/web_task_environment.cc index 9307220..1972da5 100644 --- a/ios/web/test/web_task_environment.cc +++ b/ios/web/test/web_task_environment.cc
@@ -31,17 +31,6 @@ } // namespace -WebTaskEnvironment::WebTaskEnvironment( - int options, - base::test::TaskEnvironment::TimeSource time_source) - : WebTaskEnvironment( - time_source, - ((options & IO_MAINLOOP) == IO_MAINLOOP ? MainThreadType::IO - : MainThreadType::UI), - ((options & REAL_IO_THREAD) == REAL_IO_THREAD - ? IOThreadType::REAL_THREAD - : IOThreadType::DEFAULT)) {} - WebTaskEnvironment::WebTaskEnvironment(TimeSource time_source, MainThreadType main_thread_type, IOThreadType io_thread_type,
diff --git a/ios_internal b/ios_internal index 19173a1..753730e 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 19173a1be09e94cc26a29eff04a8c70fc59699fb +Subproject commit 753730eaf49d6dd766d2dc2d1b3b0eaf83a3ec1a
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc index 5bdc3b7..b02eb46 100644 --- a/media/audio/mac/audio_manager_mac.cc +++ b/media/audio/mac/audio_manager_mac.cc
@@ -947,9 +947,19 @@ hardware_channel_layout = CHANNEL_LAYOUT_STEREO; } + // Use the input channel count and channel layout if possible. Let OSX take + // care of remapping the channels; this lets user specified channel layouts + // work correctly. + int output_channels = input_params.channels(); + ChannelLayout output_channel_layout = input_params.channel_layout(); + if (!has_valid_input_params || output_channels > hardware_channels) { + output_channels = hardware_channels; + output_channel_layout = hardware_channel_layout; + } + AudioParameters params( AudioParameters::AUDIO_PCM_LOW_LATENCY, - {hardware_channel_layout, hardware_channels}, hardware_sample_rate, + {output_channel_layout, output_channels}, hardware_sample_rate, buffer_size, AudioParameters::HardwareCapabilities( GetMinAudioBufferSizeMacOS(limits::kMinAudioBufferSize,
diff --git a/media/base/android/media_codec_bridge_impl.cc b/media/base/android/media_codec_bridge_impl.cc index 5b580a0..3430b7bb 100644 --- a/media/base/android/media_codec_bridge_impl.cc +++ b/media/base/android/media_codec_bridge_impl.cc
@@ -13,6 +13,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" +#include "base/containers/heap_array.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -629,8 +630,8 @@ // one subsample here just to be on the safe side. int num_subsamples = std::max(static_cast<size_t>(1), subsamples.size()); - std::unique_ptr<jint[]> native_clear_array(new jint[num_subsamples]); - std::unique_ptr<jint[]> native_cypher_array(new jint[num_subsamples]); + auto native_clear_array = base::HeapArray<jint>::Uninit(num_subsamples); + auto native_cypher_array = base::HeapArray<jint>::Uninit(num_subsamples); if (subsamples.empty()) { native_clear_array[0] = 0; @@ -650,9 +651,9 @@ } ScopedJavaLocalRef<jintArray> clear_array = base::android::ToJavaIntArray( - env, native_clear_array.get(), num_subsamples); + env, native_clear_array.data(), num_subsamples); ScopedJavaLocalRef<jintArray> cypher_array = base::android::ToJavaIntArray( - env, native_cypher_array.get(), num_subsamples); + env, native_cypher_array.data(), num_subsamples); MediaCodecStatus status = static_cast<MediaCodecStatus>( Java_MediaCodecBridge_queueSecureInputBuffer(
diff --git a/media/base/audio_bus_perftest.cc b/media/base/audio_bus_perftest.cc index d31a1c55..795b1be 100644 --- a/media/base/audio_bus_perftest.cc +++ b/media/base/audio_bus_perftest.cc
@@ -2,11 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/audio_bus.h" + #include <stdint.h> + #include <memory> +#include "base/containers/heap_array.h" #include "base/time/time.h" -#include "media/base/audio_bus.h" #include "media/base/audio_sample_types.h" #include "media/base/fake_audio_render_callback.h" #include "testing/gtest/include/gtest/gtest.h" @@ -34,12 +37,12 @@ const std::string& trace_name, bool to_interleaved_only = false) { const int frame_size = bus->frames() * bus->channels(); - std::unique_ptr<T[]> interleaved(new T[frame_size]); + auto interleaved = base::HeapArray<T>::Uninit(frame_size); perf_test::PerfResultReporter reporter = SetUpReporter(trace_name); base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) - bus->ToInterleaved<SampleTraits>(bus->frames(), interleaved.get()); + bus->ToInterleaved<SampleTraits>(bus->frames(), interleaved.data()); double total_time_milliseconds = (base::TimeTicks::Now() - start).InMillisecondsF(); reporter.AddResult("_to_interleaved", @@ -50,7 +53,7 @@ start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) - bus->FromInterleaved<SampleTraits>(interleaved.get(), bus->frames()); + bus->FromInterleaved<SampleTraits>(interleaved.data(), bus->frames()); total_time_milliseconds = (base::TimeTicks::Now() - start).InMillisecondsF(); reporter.AddResult("_from_interleaved", total_time_milliseconds / kBenchmarkIterations);
diff --git a/media/base/data_buffer.cc b/media/base/data_buffer.cc index 6ffb717..c3e910e 100644 --- a/media/base/data_buffer.cc +++ b/media/base/data_buffer.cc
@@ -8,31 +8,27 @@ namespace media { -DataBuffer::DataBuffer(int buffer_size) - : buffer_size_(buffer_size), - data_size_(0) { +DataBuffer::DataBuffer(int buffer_size) : data_size_(buffer_size) { CHECK_GE(buffer_size, 0); - data_ = std::make_unique<uint8_t[]>(buffer_size_); + data_ = base::HeapArray<uint8_t>::Uninit(buffer_size); } -DataBuffer::DataBuffer(std::unique_ptr<uint8_t[]> buffer, int buffer_size) - : data_(std::move(buffer)), - buffer_size_(buffer_size), - data_size_(buffer_size) { - CHECK(data_.get()); - CHECK_GE(buffer_size, 0); +DataBuffer::DataBuffer(base::HeapArray<uint8_t> buffer) + : data_size_(buffer.size()) { + data_ = std::move(buffer); + CHECK(data_.data()); } DataBuffer::DataBuffer(const uint8_t* data, int data_size) - : buffer_size_(data_size), data_size_(data_size) { + : data_size_(data_size) { if (!data) { CHECK_EQ(data_size, 0); return; } CHECK_GE(data_size, 0); - data_ = std::make_unique<uint8_t[]>(buffer_size_); - memcpy(data_.get(), data, data_size_); + data_ = base::HeapArray<uint8_t>::Uninit(data_size); + memcpy(data_.data(), data, data_size_); } DataBuffer::DataBuffer(DataBufferType data_buffer_type) : is_end_of_stream_(data_buffer_type == DataBufferType::kEndOfStream) {}
diff --git a/media/base/data_buffer.h b/media/base/data_buffer.h index f171808..7dc6e67 100644 --- a/media/base/data_buffer.h +++ b/media/base/data_buffer.h
@@ -7,9 +7,8 @@ #include <stdint.h> -#include <memory> - #include "base/check_op.h" +#include "base/containers/heap_array.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "media/base/media_export.h" @@ -28,8 +27,7 @@ // Allocates buffer of size |buffer_size| >= 0. explicit DataBuffer(int buffer_size); - // Assumes valid data of size |buffer_size|. - DataBuffer(std::unique_ptr<uint8_t[]> buffer, int buffer_size); + explicit DataBuffer(base::HeapArray<uint8_t> buffer); DataBuffer(const DataBuffer&) = delete; DataBuffer& operator=(const DataBuffer&) = delete; @@ -65,14 +63,16 @@ duration_ = duration; } + // TODO(b/335662415): Change data(), writable_data() so they always return a + // span to remove no data_size() member. const uint8_t* data() const { DCHECK(!end_of_stream()); - return data_.get(); + return data_.data(); } uint8_t* writable_data() { DCHECK(!end_of_stream()); - return data_.get(); + return data_.data(); } // The size of valid data in bytes. @@ -83,9 +83,9 @@ return data_size_; } - void set_data_size(int data_size) { + void set_data_size(size_t data_size) { DCHECK(!end_of_stream()); - CHECK_LE(data_size, buffer_size_); + CHECK_LE(data_size, data_.size()); data_size_ = data_size; } @@ -107,8 +107,7 @@ base::TimeDelta timestamp_; base::TimeDelta duration_; - std::unique_ptr<uint8_t[]> data_; - int buffer_size_; + base::HeapArray<uint8_t> data_; int data_size_; const bool is_end_of_stream_ = false; };
diff --git a/media/base/data_buffer_unittest.cc b/media/base/data_buffer_unittest.cc index ca1a97b4..c7d0215dd 100644 --- a/media/base/data_buffer_unittest.cc +++ b/media/base/data_buffer_unittest.cc
@@ -19,8 +19,8 @@ // Zero-sized buffers are valid. In practice they aren't used very much but it // eliminates clients from worrying about null data pointers. scoped_refptr<DataBuffer> buffer = new DataBuffer(0); - EXPECT_TRUE(buffer->data()); - EXPECT_TRUE(buffer->writable_data()); + EXPECT_FALSE(buffer->data()); + EXPECT_FALSE(buffer->writable_data()); EXPECT_EQ(0, buffer->data_size()); EXPECT_FALSE(buffer->end_of_stream()); } @@ -30,17 +30,17 @@ scoped_refptr<DataBuffer> buffer = new DataBuffer(10); EXPECT_TRUE(buffer->data()); EXPECT_TRUE(buffer->writable_data()); - EXPECT_EQ(0, buffer->data_size()); + EXPECT_EQ(10, buffer->data_size()); EXPECT_FALSE(buffer->end_of_stream()); } TEST(DataBufferTest, Constructor_ScopedArray) { // Data should be passed and both data and buffer size should be set. const int kSize = 8; - std::unique_ptr<uint8_t[]> data(new uint8_t[kSize]); - const uint8_t* kData = data.get(); + auto data = base::HeapArray<uint8_t>::Uninit(kSize); + const uint8_t* kData = data.data(); - scoped_refptr<DataBuffer> buffer = new DataBuffer(std::move(data), kSize); + scoped_refptr<DataBuffer> buffer = new DataBuffer(std::move(data)); EXPECT_TRUE(buffer->data()); EXPECT_TRUE(buffer->writable_data()); EXPECT_EQ(kData, buffer->data());
diff --git a/media/base/decrypt_config.cc b/media/base/decrypt_config.cc index e923172f..2b889ba 100644 --- a/media/base/decrypt_config.cc +++ b/media/base/decrypt_config.cc
@@ -63,7 +63,7 @@ std::unique_ptr<DecryptConfig> DecryptConfig::CopyNewSubsamplesIV( const std::vector<SubsampleEntry>& subsamples, - const std::string& iv) { + const std::string& iv) const { return std::make_unique<DecryptConfig>(encryption_scheme_, key_id_, iv, subsamples, encryption_pattern_); }
diff --git a/media/base/decrypt_config.h b/media/base/decrypt_config.h index 3ab59a0..4de759c 100644 --- a/media/base/decrypt_config.h +++ b/media/base/decrypt_config.h
@@ -72,7 +72,7 @@ // while providing a new vector of subsamples and initialization vector. std::unique_ptr<DecryptConfig> CopyNewSubsamplesIV( const std::vector<SubsampleEntry>& subsamples, - const std::string& iv); + const std::string& iv) const; // Returns whether this config has EncryptionPattern set or not. bool HasPattern() const;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 2a2fb34d..cb0aa2d0 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -1294,7 +1294,7 @@ // Expiry: When GLImageProcessor is deleted BASE_FEATURE(kUseGLForScaling, "UseGLForScaling", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Experimental support for GL based image processing. On some architectures, // the hardware accelerated video decoder outputs frames in a format not // understood by the display controller. We usually use LibYUV to convert these
diff --git a/media/base/user_input_monitor_win.cc b/media/base/user_input_monitor_win.cc index 2d280b5..6894798 100644 --- a/media/base/user_input_monitor_win.cc +++ b/media/base/user_input_monitor_win.cc
@@ -6,8 +6,10 @@ #include <stddef.h> #include <stdint.h> + #include <memory> +#include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/logging.h" @@ -256,10 +258,10 @@ DCHECK_EQ(0u, result); // Retrieve the input record itself. - std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); - RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); - result = GetRawInputData( - input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); + auto buffer = base::HeapArray<uint8_t>::Uninit(size); + RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.data()); + result = GetRawInputData(input_handle, RID_INPUT, buffer.data(), &size, + sizeof(RAWINPUTHEADER)); if (result == static_cast<UINT>(-1)) { PLOG(ERROR) << "GetRawInputData() failed"; return 0;
diff --git a/media/capture/video/fake_video_capture_device.cc b/media/capture/video/fake_video_capture_device.cc index 160420a7..6943a13a 100644 --- a/media/capture/video/fake_video_capture_device.cc +++ b/media/capture/video/fake_video_capture_device.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <utility> +#include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/memory/raw_ptr.h" @@ -244,7 +245,7 @@ void PaintAndDeliverNextFrame(base::TimeDelta timestamp_to_paint) override; private: - std::unique_ptr<uint8_t[]> buffer_; + base::HeapArray<uint8_t> buffer_; }; // Delivers frames using buffers provided by the client via @@ -788,7 +789,7 @@ std::unique_ptr<VideoCaptureDevice::Client> client, const FakeDeviceState* device_state) { FrameDeliverer::Initialize(pixel_format, std::move(client), device_state); - buffer_ = std::make_unique<uint8_t[]>(VideoFrame::AllocationSize( + buffer_ = base::HeapArray<uint8_t>::Uninit(VideoFrame::AllocationSize( pixel_format, device_state->format.frame_size)); } @@ -799,11 +800,11 @@ const auto& frame_format = device_state()->format; const size_t frame_size = VideoFrame::AllocationSize( frame_format.pixel_format, frame_format.frame_size); - memset(buffer_.get(), 0, frame_size); - frame_painter()->PaintFrame(timestamp_to_paint, buffer_.get()); + memset(buffer_.data(), 0, frame_size); + frame_painter()->PaintFrame(timestamp_to_paint, buffer_.data()); base::TimeTicks now = base::TimeTicks::Now(); client()->OnIncomingCapturedData( - buffer_.get(), frame_size, device_state()->format, + buffer_.data(), frame_size, device_state()->format, GetDefaultColorSpace(device_state()->format.pixel_format), 0 /* rotation */, false /* flip_y */, now, CalculateTimeSinceFirstInvocation(now), std::nullopt);
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc index 62a7ed4..cdb44a5 100644 --- a/media/capture/video/win/video_capture_device_win.cc +++ b/media/capture/video/win/video_capture_device_win.cc
@@ -13,6 +13,7 @@ #include <list> #include <utility> +#include "base/containers/heap_array.h" #include "base/feature_list.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/metrics/histogram_functions.h" @@ -139,10 +140,10 @@ return; } - std::unique_ptr<BYTE[]> caps(new BYTE[byte_size]); + auto caps = base::HeapArray<BYTE>::Uninit(byte_size); for (int i = 0; i < count; ++i) { VideoCaptureDeviceWin::ScopedMediaType media_type; - hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); + hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.data()); // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() // macros here since they'll trigger incorrectly. if (hr != S_OK || !media_type.get()) { @@ -452,14 +453,14 @@ return; } - std::unique_ptr<BYTE[]> caps(new BYTE[size]); + auto caps = base::HeapArray<BYTE>::Uninit(size); ScopedMediaType media_type; // Get the windows capability from the capture device. // GetStreamCaps can return S_FALSE which we consider an error. Therefore the // FAILED macro can't be used. hr = stream_config->GetStreamCaps(found_capability.media_type_index, - media_type.Receive(), caps.get()); + media_type.Receive(), caps.data()); if (hr != S_OK) { SetErrorState(media::VideoCaptureError:: kWinDirectShowFailedToGetCaptureDeviceCapabilities,
diff --git a/media/filters/dav1d_video_decoder.cc b/media/filters/dav1d_video_decoder.cc index 3370191..474e945 100644 --- a/media/filters/dav1d_video_decoder.cc +++ b/media/filters/dav1d_video_decoder.cc
@@ -416,12 +416,14 @@ fake_uv_data_ = base::MakeRefCounted<base::RefCountedBytes>(size_needed); - uint16_t* data = fake_uv_data_->front_as<uint16_t>(); + uint16_t* data = + reinterpret_cast<uint16_t*>(fake_uv_data_->as_vector().data()); std::fill(data, data + size_needed / 2, kBlankUV); } } - u_plane = v_plane = fake_uv_data_->front_as<uint8_t>(); + u_plane = v_plane = + reinterpret_cast<uint8_t*>(fake_uv_data_->as_vector().data()); } auto frame = VideoFrame::WrapExternalYuvData(
diff --git a/media/filters/vp9_parser.cc b/media/filters/vp9_parser.cc index 3e51d76c..12ee9f7 100644 --- a/media/filters/vp9_parser.cc +++ b/media/filters/vp9_parser.cc
@@ -190,7 +190,7 @@ uint32_t frame_size, size_t* current_subsample_index, size_t* extra_clear_subsample_bytes, - DecryptConfig* base_decrypt_config, + const DecryptConfig* base_decrypt_config, const std::vector<SubsampleEntry>& subsamples, std::string* iv) { // We copy iv so that we can use the starting value in our @@ -666,43 +666,51 @@ return IncrementIV(iv, by); } -// Annex B Superframes -base::circular_deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { - const uint8_t* stream = stream_; - off_t bytes_left = bytes_left_; - - // Make sure we don't parse stream_ more than once. - stream_ = nullptr; - bytes_left_ = 0; - - base::circular_deque<FrameInfo> frames; - - if (bytes_left < 1) { - return frames; +// static +bool Vp9Parser::IsSuperframe(const uint8_t* stream, + off_t stream_size, + const DecryptConfig* decrypt_config) { + if (!stream || stream_size < 1) { + return false; } // The marker byte might be encrypted, in which case we should treat // the stream as a single frame. - off_t marker_offset = bytes_left - 1; - if (stream_decrypt_config_) { - if (IsByteNEncrypted(marker_offset, stream_decrypt_config_->subsamples())) { - frames.push_back(FrameInfo(stream, bytes_left)); - frames[0].decrypt_config = stream_decrypt_config_->Clone(); - return frames; - } + off_t marker_offset = stream_size - 1; + if (decrypt_config && + IsByteNEncrypted(marker_offset, decrypt_config->subsamples())) { + return false; } // If this is a superframe, the last byte in the stream will contain the // superframe marker. If not, the whole buffer contains a single frame. uint8_t marker = *(stream + marker_offset); - if ((marker & 0xe0) != 0xc0) { + return ((marker & 0xe0) == 0xc0); +} + +// static +base::circular_deque<Vp9Parser::FrameInfo> Vp9Parser::ExtractFrames( + const uint8_t* stream, + off_t stream_size, + const DecryptConfig* decrypt_config) { + base::circular_deque<FrameInfo> frames; + off_t bytes_left = stream_size; + + if (!stream || bytes_left < 1) { + return frames; + } + + if (!IsSuperframe(stream, bytes_left, decrypt_config)) { frames.push_back(FrameInfo(stream, bytes_left)); - if (stream_decrypt_config_) { - frames[0].decrypt_config = stream_decrypt_config_->Clone(); + if (decrypt_config) { + frames[0].decrypt_config = decrypt_config->Clone(); } return frames; } + off_t marker_offset = stream_size - 1; + uint8_t marker = *(stream + marker_offset); + DVLOG(1) << "Parsing a superframe"; // The bytes immediately before the superframe marker constitute superframe @@ -732,9 +740,9 @@ std::vector<SubsampleEntry> subsamples; size_t current_subsample = 0; size_t extra_clear_subsample_bytes = 0; - if (stream_decrypt_config_) { - iv = stream_decrypt_config_->iv(); - subsamples = stream_decrypt_config_->subsamples(); + if (decrypt_config) { + iv = decrypt_config->iv(); + subsamples = decrypt_config->subsamples(); } for (size_t i = 0; i < num_frames; ++i) { @@ -755,7 +763,7 @@ if (subsamples.size()) { std::unique_ptr<DecryptConfig> frame_dc = SplitSubsamples( size, ¤t_subsample, &extra_clear_subsample_bytes, - stream_decrypt_config_.get(), subsamples, &iv); + decrypt_config, subsamples, &iv); if (!frame_dc) { DVLOG(1) << "Failed to calculate decrypt config for frame " << i; frames.clear(); @@ -775,6 +783,18 @@ return frames; } +// Annex B Superframes +base::circular_deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSuperframe() { + const uint8_t* stream = stream_; + off_t bytes_left = bytes_left_; + + // Make sure we don't parse stream_ more than once. + stream_ = nullptr; + bytes_left_ = 0; + + return ExtractFrames(stream, bytes_left, stream_decrypt_config_.get()); +} + base::circular_deque<Vp9Parser::FrameInfo> Vp9Parser::ParseSVCFrame() { if (parsing_compressed_header_) { LOG(ERROR) << "Vp9Parser doesn't support parsing SVC stream when "
diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h index 02e9052..209f0fe 100644 --- a/media/filters/vp9_parser.h +++ b/media/filters/vp9_parser.h
@@ -318,6 +318,30 @@ ReferenceSlot ref_slots_[kVp9NumRefFrames]; }; + // Stores start pointer and size of each frame within the current superframe. + struct FrameInfo { + FrameInfo(); + FrameInfo(const FrameInfo& copy_from); + FrameInfo(const uint8_t* ptr, off_t size); + ~FrameInfo(); + + FrameInfo& operator=(const FrameInfo& copy_from); + bool IsValid() const { return ptr != nullptr; } + void Reset() { ptr = nullptr; } + + // Starting address of the frame. + const uint8_t* ptr = nullptr; + + // Size of the frame in bytes. + off_t size = 0; + + // Necessary height and width to decode the frame. + // This is filled only if the stream is SVC. + gfx::Size allocate_size; + + std::unique_ptr<DecryptConfig> decrypt_config; + }; + // See homonymous member variable for information on the parameter. explicit Vp9Parser(bool parsing_compressed_header); @@ -369,31 +393,20 @@ // Clear parser state and return to an initialized state. void Reset(); + // Determines if the passed in VP9 frame data contains a superframe or not. + static bool IsSuperframe(const uint8_t* stream, + off_t stream_size, + const DecryptConfig* decrypt_config); + + // Extracts the frame information for a frame, if this is a superframe then + // the returned list will contain each of the frames in decode order. An empty + // list will be returned in the error case. + static base::circular_deque<FrameInfo> ExtractFrames( + const uint8_t* stream, + off_t stream_size, + const DecryptConfig* decrypt_config); + private: - // Stores start pointer and size of each frame within the current superframe. - struct FrameInfo { - FrameInfo(); - FrameInfo(const FrameInfo& copy_from); - FrameInfo(const uint8_t* ptr, off_t size); - ~FrameInfo(); - - FrameInfo& operator=(const FrameInfo& copy_from); - bool IsValid() const { return ptr != nullptr; } - void Reset() { ptr = nullptr; } - - // Starting address of the frame. - const uint8_t* ptr = nullptr; - - // Size of the frame in bytes. - off_t size = 0; - - // Necessary height and width to decode the frame. - // This is filled only if the stream is SVC. - gfx::Size allocate_size; - - std::unique_ptr<DecryptConfig> decrypt_config; - }; - base::circular_deque<FrameInfo> ParseSuperframe(); // Parses a frame in SVC stream with |spatial_layer_frame_size_|. base::circular_deque<FrameInfo> ParseSVCFrame();
diff --git a/media/gpu/chromeos/chromeos_compressed_gpu_memory_buffer_video_frame_utils.h b/media/gpu/chromeos/chromeos_compressed_gpu_memory_buffer_video_frame_utils.h index 59132f8c..647d6e08 100644 --- a/media/gpu/chromeos/chromeos_compressed_gpu_memory_buffer_video_frame_utils.h +++ b/media/gpu/chromeos/chromeos_compressed_gpu_memory_buffer_video_frame_utils.h
@@ -6,6 +6,7 @@ #define MEDIA_GPU_CHROMEOS_CHROMEOS_COMPRESSED_GPU_MEMORY_BUFFER_VIDEO_FRAME_UTILS_H_ #include <memory> +#include <vector> #include "base/memory/scoped_refptr.h"
diff --git a/media/gpu/chromeos/decoder_buffer_transcryptor.cc b/media/gpu/chromeos/decoder_buffer_transcryptor.cc index f5abbf9..0b98cd4 100644 --- a/media/gpu/chromeos/decoder_buffer_transcryptor.cc +++ b/media/gpu/chromeos/decoder_buffer_transcryptor.cc
@@ -8,6 +8,7 @@ #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h" +#include "media/filters/vp9_parser.h" #include "media/gpu/chromeos/video_decoder_pipeline.h" namespace media { @@ -24,11 +25,13 @@ DecoderBufferTranscryptor::DecoderBufferTranscryptor( CdmContext* cdm_context, VideoDecoderMixin& decoder, + bool needs_vp9_superframe_splitting, OnBufferTranscryptedCB transcrypt_callback, WaitingCB waiting_callback) : decoder_(decoder), transcrypt_callback_(std::move(transcrypt_callback)), - waiting_callback_(std::move(waiting_callback)) { + waiting_callback_(std::move(waiting_callback)), + needs_vp9_superframe_splitting_(needs_vp9_superframe_splitting) { weak_this_ = weak_this_factory_.GetWeakPtr(); DCHECK(cdm_context); @@ -56,7 +59,7 @@ scoped_refptr<DecoderBuffer> buffer, VideoDecoder::DecodeCB decode_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - transcrypt_task_queue_.emplace(std::move(buffer), std::move(decode_cb)); + transcrypt_task_queue_.emplace_back(std::move(buffer), std::move(decode_cb)); DecryptPendingBuffer(); } @@ -69,7 +72,7 @@ while (!transcrypt_task_queue_.empty()) { std::move(transcrypt_task_queue_.front().decode_done_cb).Run(status); - transcrypt_task_queue_.pop(); + transcrypt_task_queue_.pop_front(); } } @@ -93,17 +96,85 @@ if (transcrypt_task_queue_.empty()) return; current_transcrypt_task_ = std::move(transcrypt_task_queue_.front()); - transcrypt_task_queue_.pop(); + transcrypt_task_queue_.pop_front(); } - if (current_transcrypt_task_->buffer->end_of_stream()) { + DecoderBuffer* curr_buffer = current_transcrypt_task_->buffer.get(); + if (curr_buffer->end_of_stream()) { OnBufferTranscrypted(Decryptor::kSuccess, current_transcrypt_task_->buffer); return; } + // Check if we need to split VP9 superframes. + if (needs_vp9_superframe_splitting_ && + Vp9Parser::IsSuperframe(curr_buffer->data(), + base::checked_cast<off_t>(curr_buffer->size()), + curr_buffer->decrypt_config())) { + base::circular_deque<Vp9Parser::FrameInfo> frames = + Vp9Parser::ExtractFrames(curr_buffer->data(), + base::checked_cast<off_t>(curr_buffer->size()), + curr_buffer->decrypt_config()); + if (frames.empty()) { + LOG(ERROR) << "Failure in Vp9 superframe splitting"; + OnBufferTranscrypted(Decryptor::kError, nullptr); + return; + } + + // Save the original DecoderBuffer for the rest of our operations that has + // the whole superframe to keep its data valid until we are done and also to + // use for metadata reference. + scoped_refptr<DecoderBuffer> superframe = + std::move(current_transcrypt_task_->buffer); + + // Put the first frame in place of the |current_transcrypt_task_|'s buffer, + // then add the rest to the queue. + current_transcrypt_task_->buffer = DecoderBuffer::CopyFrom( + frames.front().ptr, base::checked_cast<size_t>(frames.front().size)); + curr_buffer = current_transcrypt_task_->buffer.get(); + + // We only copy this limited set of fields to match what we do in the + // corresponding Decryptor implementation in: + // chromeos::ContentDecryptionModuleAdapter::OnDecrypt + current_transcrypt_task_->buffer->set_timestamp(superframe->timestamp()); + current_transcrypt_task_->buffer->set_duration(superframe->duration()); + current_transcrypt_task_->buffer->set_is_key_frame( + superframe->is_key_frame()); + current_transcrypt_task_->buffer->set_side_data(superframe->side_data()); + if (frames.front().decrypt_config) { + current_transcrypt_task_->buffer->set_decrypt_config( + std::move(frames.front().decrypt_config)); + } + frames.pop_front(); + + // The last one in the queue should have the decode done callback and the + // rest should be DoNothing. + VideoDecoder::DecodeCB next_decode_done_cb; + if (!frames.empty()) { + next_decode_done_cb = std::move(current_transcrypt_task_->decode_done_cb); + current_transcrypt_task_->decode_done_cb = base::DoNothing(); + } + while (!frames.empty()) { + // The |frames| are in decode order, so we take from the back of |frames| + // and append to the front of |transcrypt_task_queue_|. + scoped_refptr<DecoderBuffer> buffer = DecoderBuffer::CopyFrom( + frames.back().ptr, base::checked_cast<size_t>(frames.back().size)); + buffer->set_timestamp(superframe->timestamp()); + buffer->set_duration(superframe->duration()); + buffer->set_is_key_frame(superframe->is_key_frame()); + buffer->set_side_data(superframe->side_data()); + if (frames.back().decrypt_config) { + buffer->set_decrypt_config(std::move(frames.back().decrypt_config)); + } + frames.pop_back(); + transcrypt_task_queue_.emplace_front(std::move(buffer), + std::move(next_decode_done_cb)); + next_decode_done_cb = base::DoNothing(); + } + } + // If we've already attached a secure buffer, don't do it again. - if (!current_transcrypt_task_->buffer->has_side_data() || - !current_transcrypt_task_->buffer->side_data()->secure_handle) { + if (!curr_buffer->has_side_data() || + !curr_buffer->side_data()->secure_handle) { auto status = decoder_->AttachSecureBuffer(current_transcrypt_task_->buffer); if (status == CroStatus::Codes::kSecureBufferPoolEmpty) { @@ -116,14 +187,14 @@ return; } - if (current_transcrypt_task_->buffer->has_side_data() && - current_transcrypt_task_->buffer->side_data()->secure_handle) { + if (curr_buffer->has_side_data() && + curr_buffer->side_data()->secure_handle) { // Wrap the callback so we can release the secure buffer when decoding is // done. - current_transcrypt_task_->decode_done_cb = base::BindOnce( - &DecoderBufferTranscryptor::OnSecureBufferRelease, weak_this_, - current_transcrypt_task_->buffer->side_data()->secure_handle, - std::move(current_transcrypt_task_->decode_done_cb)); + current_transcrypt_task_->decode_done_cb = + base::BindOnce(&DecoderBufferTranscryptor::OnSecureBufferRelease, + weak_this_, curr_buffer->side_data()->secure_handle, + std::move(current_transcrypt_task_->decode_done_cb)); } } transcrypt_pending_ = true;
diff --git a/media/gpu/chromeos/decoder_buffer_transcryptor.h b/media/gpu/chromeos/decoder_buffer_transcryptor.h index 3c1f5a1..217556f 100644 --- a/media/gpu/chromeos/decoder_buffer_transcryptor.h +++ b/media/gpu/chromeos/decoder_buffer_transcryptor.h
@@ -8,7 +8,7 @@ #include <memory> #include <optional> -#include "base/containers/queue.h" +#include "base/containers/circular_deque.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" @@ -38,6 +38,7 @@ // will be called with a nullptr in the event of failure. DecoderBufferTranscryptor(CdmContext* cdm_context, VideoDecoderMixin& decoder, + bool needs_vp9_superframe_splitting, OnBufferTranscryptedCB transcrypt_callback, WaitingCB waiting_callback); DecoderBufferTranscryptor(const DecoderBufferTranscryptor&) = delete; @@ -98,7 +99,7 @@ bool key_added_while_decrypting_ = false; // Queue containing all requested transcrypt tasks. - base::queue<TranscryptTask> transcrypt_task_queue_; + base::circular_deque<TranscryptTask> transcrypt_task_queue_; // The transcrypt task we're currently trying to execute. std::optional<TranscryptTask> current_transcrypt_task_; @@ -111,6 +112,10 @@ // before moving on after a Reset. bool transcrypt_pending_ = false; + // If true, then we should split VP9 superframes up into individual frames + // before decryption/decode. + const bool needs_vp9_superframe_splitting_; + // We need to use a CdmContextRef so that we destruct // |cdm_event_cb_registration_| before the CDM is destructed. The CDM has // mechanisms to ensure destruction on the proper thread.
diff --git a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc index af0513af..51f17eb 100644 --- a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc +++ b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc
@@ -106,7 +106,7 @@ scoped_refptr<VideoFrame> GenericDmaBufVideoFrameMapper::MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const { + int permissions) { if (!video_frame) { LOG(ERROR) << "Video frame is nullptr"; return nullptr;
diff --git a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.h b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.h index 0bfc6a3..f84283b 100644 --- a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.h +++ b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.h
@@ -25,7 +25,7 @@ // VideoFrameMapper implementation. scoped_refptr<VideoFrame> MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const override; + int permissions) override; private: explicit GenericDmaBufVideoFrameMapper(VideoPixelFormat format);
diff --git a/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.cc b/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.cc index 354d2491..d4f0df53 100644 --- a/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.cc +++ b/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.cc
@@ -25,7 +25,7 @@ scoped_refptr<VideoFrame> GpuMemoryBufferVideoFrameMapper::MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const { + int permissions) { if (!video_frame) { LOG(ERROR) << "Video frame is nullptr"; return nullptr;
diff --git a/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.h b/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.h index 77836f31..93eda06d 100644 --- a/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.h +++ b/media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.h
@@ -28,7 +28,7 @@ // VideoFrameMapper implementation. scoped_refptr<VideoFrame> MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const override; + int permissions) override; private: explicit GpuMemoryBufferVideoFrameMapper(VideoPixelFormat format);
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc index 0986ecc5..2b7ef8e 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.cc +++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -630,6 +630,11 @@ estimated_num_buffers_for_renderer_ = EstimateRequiredRendererPipelineBuffers(low_delay); +#if BUILDFLAG(USE_V4L2_CODEC) + decryption_needs_vp9_superframe_splitting_ = + config.codec() == VideoCodec::kVP9; +#endif + #if BUILDFLAG(USE_VAAPI) if (ignore_resolution_changes_to_smaller_for_testing_) { static_cast<VaapiVideoDecoder*>(decoder_.get()) @@ -687,7 +692,7 @@ } else { // We need to enable transcryption for protected content. buffer_transcryptor_ = std::make_unique<DecoderBufferTranscryptor>( - cdm_context, *decoder_, + cdm_context, *decoder_, decryption_needs_vp9_superframe_splitting_, base::BindRepeating(&VideoDecoderPipeline::OnBufferTranscrypted, decoder_weak_this_), base::BindRepeating(&VideoDecoderPipeline::OnDecoderWaiting,
diff --git a/media/gpu/chromeos/video_decoder_pipeline.h b/media/gpu/chromeos/video_decoder_pipeline.h index 2c7a1a6..27e8b7b 100644 --- a/media/gpu/chromeos/video_decoder_pipeline.h +++ b/media/gpu/chromeos/video_decoder_pipeline.h
@@ -483,6 +483,11 @@ // See VP9Decoder for information on this. bool ignore_resolution_changes_to_smaller_for_testing_ = false; + // If we will need to tell the DecoderBufferTranscryptor to do VP9 superframe + // splitting. + bool decryption_needs_vp9_superframe_splitting_ + GUARDED_BY_CONTEXT(decoder_sequence_checker_) = false; + base::WeakPtr<VideoDecoderPipeline> decoder_weak_this_; // The weak pointer of this, bound to |decoder_task_runner_|. base::WeakPtrFactory<VideoDecoderPipeline> decoder_weak_this_factory_{this};
diff --git a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc index 6e627e4..9e578e4d 100644 --- a/media/gpu/chromeos/video_decoder_pipeline_unittest.cc +++ b/media/gpu/chromeos/video_decoder_pipeline_unittest.cc
@@ -51,6 +51,11 @@ return arg.code() == status_code; } +MATCHER_P(MatchesDecoderBuffer, buffer, "") { + DCHECK(arg); + return arg->MatchesForTesting(*buffer); +} + class MockVideoFramePool : public DmabufVideoFramePool { public: MockVideoFramePool() = default; @@ -205,12 +210,14 @@ /*uses_oop_video_decoder=*/false, /*in_video_decoder_process=*/true)); - SetSupportedVideoDecoderConfigs({SupportedVideoDecoderConfig( - /*profile_min,=*/VP8PROFILE_ANY, - /*profile_max=*/VP8PROFILE_ANY, kMinSupportedResolution, - kMaxSupportedResolution, - /*allow_encrypted=*/true, - /*require_encrypted=*/false)}); + SetSupportedVideoDecoderConfigs({ + SupportedVideoDecoderConfig( + /*profile_min,=*/VP8PROFILE_ANY, + /*profile_max=*/VP9PROFILE_PROFILE0, kMinSupportedResolution, + kMaxSupportedResolution, + /*allow_encrypted=*/true, + /*require_encrypted=*/false), + }); } ~VideoDecoderPipelineTest() override = default; @@ -261,8 +268,15 @@ } #if BUILDFLAG(IS_CHROMEOS_ASH) - void InitializeForTranscrypt() { + void InitializeForTranscrypt(bool vp9 = false) { decoder_->allow_encrypted_content_for_testing_ = true; + if (vp9) { + config_ = VideoDecoderConfig( + VideoCodec::kVP9, VP9PROFILE_PROFILE0, + VideoDecoderConfig::AlphaMode::kIsOpaque, VideoColorSpace(), + kNoTransformation, kCodedSize, gfx::Rect(kCodedSize), kCodedSize, + EmptyExtraData(), EncryptionScheme::kCenc); + } EXPECT_CALL(cdm_context_, GetChromeOsCdmContext()) .WillRepeatedly(Return(&chromeos_cdm_context_)); EXPECT_CALL(cdm_context_, RegisterEventCB(_)) @@ -383,7 +397,7 @@ } base::test::TaskEnvironment task_environment_; - const VideoDecoderConfig config_; + VideoDecoderConfig config_; #if BUILDFLAG(IS_CHROMEOS_ASH) MockCdmContext cdm_context_; // Keep this before |decoder_|. @@ -862,6 +876,192 @@ base::Unretained(this))); task_environment_.RunUntilIdle(); } + +#if BUILDFLAG(USE_V4L2_CODEC) +TEST_F(VideoDecoderPipelineTest, SplitVp9Superframe) { + InitializeForTranscrypt(true); + + // This one requires specially crafted DecoderBuffer data so that the frame + // split occurs. The superframe (which contains 2 frames) gets sent into the + // pipeline for decoding, it then goes into the transcryptor...but then before + // it gets sent for decrypt + decode it should get split into the 2 separate + // frames. + + constexpr uint8_t kEncryptedSuperframe[] = { + // Frame 0 + // Clear data + 1, + 2, + 3, + 4, + // Encrypted Data (one block to cause IV increment) + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + // Frame 1 + // Clear data + 5, + 6, + 7, + 8, + 9, + 10, + // Encrypted Data (must be at least a block size) + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + // Superframe marker (2 frames, mag 1) + 0xc1, + // Frame sizes (1 byte each) + 0x14, + 0x16, + // Superframe marker (2 frames, mag 1) + 0xc1, + }; + constexpr uint8_t kEncryptedFrame0[] = { + // Clear data + 1, + 2, + 3, + 4, + // Encrypted Data (one block to cause IV increment) + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + }; + constexpr uint8_t kEncryptedFrame1[] = { + // Clear data + 5, + 6, + 7, + 8, + 9, + 10, + // Encrypted Data (must be at least a block size) + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + }; + + scoped_refptr<DecoderBuffer> superframe_buffer = DecoderBuffer::CopyFrom( + kEncryptedSuperframe, sizeof(kEncryptedSuperframe)); + superframe_buffer->set_decrypt_config(DecryptConfig::CreateCencConfig( + "fakekey", std::string(16, '0'), + {SubsampleEntry(4, 16), SubsampleEntry(6, 16), SubsampleEntry(4, 0)})); + + std::string iv(16, '0'); + scoped_refptr<DecoderBuffer> frame0_buffer = + DecoderBuffer::CopyFrom(kEncryptedFrame0, sizeof(kEncryptedFrame0)); + frame0_buffer->set_decrypt_config( + DecryptConfig::CreateCencConfig("fakekey", iv, {SubsampleEntry(4, 16)})); + + scoped_refptr<DecoderBuffer> frame1_buffer = + DecoderBuffer::CopyFrom(kEncryptedFrame1, sizeof(kEncryptedFrame1)); + // The IV should be incremented by one. + iv[15]++; + frame1_buffer->set_decrypt_config( + DecryptConfig::CreateCencConfig("fakekey", iv, {SubsampleEntry(6, 16)})); + + { + InSequence sequence; + EXPECT_CALL(*reinterpret_cast<MockDecoder*>(GetUnderlyingDecoder()), + AttachSecureBuffer(MatchesDecoderBuffer(frame0_buffer))) + .WillOnce(Return(CroStatus::Codes::kOk)); + EXPECT_CALL(decryptor_, Decrypt(Decryptor::kVideo, + MatchesDecoderBuffer(frame0_buffer), _)) + .WillOnce([&frame0_buffer](Decryptor::StreamType stream_type, + scoped_refptr<DecoderBuffer> encrypted, + Decryptor::DecryptCB decrypt_cb) { + std::move(decrypt_cb).Run(Decryptor::kSuccess, frame0_buffer); + }); + EXPECT_CALL(*reinterpret_cast<MockDecoder*>(GetUnderlyingDecoder()), + Decode(MatchesDecoderBuffer(frame0_buffer), _)) + .WillOnce([](scoped_refptr<DecoderBuffer> transcrypted, + VideoDecoderMixin::DecodeCB decode_cb) { + std::move(decode_cb).Run(DecoderStatus::Codes::kOk); + }); + EXPECT_CALL(*reinterpret_cast<MockDecoder*>(GetUnderlyingDecoder()), + AttachSecureBuffer(MatchesDecoderBuffer(frame1_buffer))) + .WillOnce(Return(CroStatus::Codes::kOk)); + EXPECT_CALL(decryptor_, Decrypt(Decryptor::kVideo, + MatchesDecoderBuffer(frame1_buffer), _)) + .WillOnce([&frame1_buffer](Decryptor::StreamType stream_type, + scoped_refptr<DecoderBuffer> encrypted, + Decryptor::DecryptCB decrypt_cb) { + std::move(decrypt_cb).Run(Decryptor::kSuccess, frame1_buffer); + }); + EXPECT_CALL(*reinterpret_cast<MockDecoder*>(GetUnderlyingDecoder()), + Decode(MatchesDecoderBuffer(frame1_buffer), _)) + .WillOnce([](scoped_refptr<DecoderBuffer> transcrypted, + VideoDecoderMixin::DecodeCB decode_cb) { + std::move(decode_cb).Run(DecoderStatus::Codes::kOk); + }); + EXPECT_CALL(*this, + OnDecodeDone(MatchesStatusCode(DecoderStatus::Codes::kOk))); + } + decoder_->Decode(std::move(superframe_buffer), + base::BindOnce(&VideoDecoderPipelineTest::OnDecodeDone, + base::Unretained(this))); + task_environment_.RunUntilIdle(); + + testing::Mock::VerifyAndClearExpectations(&decryptor_); + testing::Mock::VerifyAndClearExpectations( + reinterpret_cast<MockDecoder*>(GetUnderlyingDecoder())); + testing::Mock::VerifyAndClearExpectations(this); +} +#endif // BUILDFLAG(USE_V4L2_CODEC) #endif // BUILDFLAG(IS_CHROMEOS_ASH) // Verifies the algorithm for choosing formats in PickDecoderOutputFormat works
diff --git a/media/gpu/mac/vp9_super_frame_bitstream_filter.cc b/media/gpu/mac/vp9_super_frame_bitstream_filter.cc index 6daad027..01ce508d 100644 --- a/media/gpu/mac/vp9_super_frame_bitstream_filter.cc +++ b/media/gpu/mac/vp9_super_frame_bitstream_filter.cc
@@ -7,6 +7,7 @@ #include "base/apple/osstatus_logging.h" #include "base/bits.h" #include "base/check.h" +#include "base/containers/heap_array.h" #include "base/logging.h" #include "media/filters/vp9_raw_bits_reader.h" @@ -192,7 +193,7 @@ // Write superframe trailer which has size information for each buffer. size_t trailer_offset = 0; const size_t trailer_size = total_size - offset; - std::unique_ptr<uint8_t[]> trailer(new uint8_t[trailer_size]); + auto trailer = base::HeapArray<uint8_t>::Uninit(trailer_size); const uint8_t marker = kSuperFrameMarker + ((bytes_per_frame_size - 1) << 3) + (partial_buffers_.size() - 1); @@ -208,7 +209,7 @@ DCHECK_EQ(trailer_offset, trailer_size - 1); trailer[trailer_offset] = marker; - OSStatus status = CMBlockBufferReplaceDataBytes(trailer.get(), data_.get(), + OSStatus status = CMBlockBufferReplaceDataBytes(trailer.data(), data_.get(), offset, trailer_size); if (status != noErr) { OSSTATUS_DLOG(ERROR, status) << "CMBlockBufferReplaceDataBytes failed.";
diff --git a/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc b/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc index d514e1f..fe75c6f 100644 --- a/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc +++ b/media/gpu/v4l2/stateless/v4l2_stateless_video_decoder.cc
@@ -482,7 +482,9 @@ // push and let the dequeue handle frame output. display_queue_.push(std::move(dec_surface)); - ServiceDisplayQueue(); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&V4L2StatelessVideoDecoder::ServiceDisplayQueue, + weak_ptr_factory_for_events_.GetWeakPtr())); } void V4L2StatelessVideoDecoder::ServiceDisplayQueue() { @@ -647,24 +649,25 @@ DCHECK(!surfaces_queued_.empty()); DVLOGF(4); - auto surface = std::move(surfaces_queued_.front()); - surfaces_queued_.pop(); - // |output_queue_| is responsible for tracking which buffers correspond to // which frames. The queue needs to know that the buffer is done, ready for // display, and should not be queued. auto output_buffer = output_queue_->DequeueBuffer(); - // TODO(frkoenig): Handle |output_buffer| being a std::nullopt - last_frame_id_dequeued_ = output_buffer->GetTimeAsFrameID(); + if (output_buffer) { + auto surface = std::move(surfaces_queued_.front()); + surfaces_queued_.pop(); - DCHECK_EQ(surface->FrameID(), last_frame_id_dequeued_) - << "The surfaces are queued as the buffer is submitted. They are " - "expected to be dequeued in order."; + last_frame_id_dequeued_ = output_buffer->GetTimeAsFrameID(); - // References that this frame holds can be removed once the frame is done - // decoding. - surface->ClearReferenceSurfaces(); + DCHECK_EQ(surface->FrameID(), last_frame_id_dequeued_) + << "The surfaces are queued as the buffer is submitted. They are " + "expected to be dequeued in order."; + + // References that this frame holds can be removed once the frame is done + // decoding. + surface->ClearReferenceSurfaces(); + } // Put the just dequeued buffer into the list of available input buffers. input_queue_->DequeueBuffer(); @@ -673,9 +676,14 @@ // occur when there are no more surfaces. Another reason to try is EOS // handling. The EOS packet does not need a surface, but can get stuck behind // a decode request. - ServiceDisplayQueue(); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&V4L2StatelessVideoDecoder::ServiceDisplayQueue, + weak_ptr_factory_for_events_.GetWeakPtr())); - ServiceDecodeRequestQueue(); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(&V4L2StatelessVideoDecoder::ServiceDecodeRequestQueue, + weak_ptr_factory_for_events_.GetWeakPtr())); } void V4L2StatelessVideoDecoder::EnqueueDecodedOutputBufferByFrameID(
diff --git a/media/gpu/v4l2/v4l2_video_decoder_delegate_h264.cc b/media/gpu/v4l2/v4l2_video_decoder_delegate_h264.cc index 740f3bb..b960344a 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_delegate_h264.cc +++ b/media/gpu/v4l2/v4l2_video_decoder_delegate_h264.cc
@@ -10,6 +10,7 @@ #include <algorithm> #include <type_traits> +#include "base/containers/heap_array.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "build/chromeos_buildflags.h" @@ -531,11 +532,11 @@ ? Status::kOk : Status::kFail; } - std::unique_ptr<uint8_t[]> data_copy(new uint8_t[data_copy_size]); - memset(data_copy.get(), 0, data_copy_size); + auto data_copy = base::HeapArray<uint8_t>::Uninit(data_copy_size); + memset(data_copy.data(), 0, data_copy_size); data_copy[2] = 0x01; - memcpy(data_copy.get() + 3, data, size); - return surface_handler_->SubmitSlice(dec_surface.get(), data_copy.get(), + memcpy(data_copy.data() + 3, data, size); + return surface_handler_->SubmitSlice(dec_surface.get(), data_copy.data(), data_copy_size) ? Status::kOk : Status::kFail;
diff --git a/media/gpu/v4l2/v4l2_video_decoder_delegate_h265.cc b/media/gpu/v4l2/v4l2_video_decoder_delegate_h265.cc index e0d51793..704bd58 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_delegate_h265.cc +++ b/media/gpu/v4l2/v4l2_video_decoder_delegate_h265.cc
@@ -494,11 +494,11 @@ ? Status::kOk : Status::kFail; } - std::unique_ptr<uint8_t[]> data_copy(new uint8_t[data_copy_size]); - memset(data_copy.get(), 0, data_copy_size); + auto data_copy = base::HeapArray<uint8_t>::Uninit(data_copy_size); + memset(data_copy.data(), 0, data_copy_size); data_copy[2] = 0x01; - memcpy(data_copy.get() + 3, data, size); - return surface_handler_->SubmitSlice(dec_surface.get(), data_copy.get(), + memcpy(data_copy.data() + 3, data, size); + return surface_handler_->SubmitSlice(dec_surface.get(), data_copy.data(), data_copy_size) ? Status::kOk : Status::kFail;
diff --git a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc index 03845fe..c088df0 100644 --- a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc +++ b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc
@@ -111,26 +111,34 @@ auto video_frame_mapper = base::WrapUnique(new VaapiDmaBufVideoFrameMapper(format)); - if (!video_frame_mapper->vaapi_wrapper_) - return nullptr; return video_frame_mapper; } VaapiDmaBufVideoFrameMapper::VaapiDmaBufVideoFrameMapper( VideoPixelFormat format) - : VideoFrameMapper(format), - vaapi_wrapper_(VaapiWrapper::Create(VaapiWrapper::kVideoProcess, - VAProfileNone, - EncryptionScheme::kUnencrypted, - base::DoNothing()) - .value_or(nullptr)) {} + : VideoFrameMapper(format) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} -VaapiDmaBufVideoFrameMapper::~VaapiDmaBufVideoFrameMapper() {} +VaapiDmaBufVideoFrameMapper::~VaapiDmaBufVideoFrameMapper() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} scoped_refptr<VideoFrame> VaapiDmaBufVideoFrameMapper::MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const { + int permissions) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!vaapi_wrapper_) { + vaapi_wrapper_ = + VaapiWrapper::Create(VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::DoNothing()) + .value_or(nullptr); + if (!vaapi_wrapper_) { + VLOGF(1) << "Failed to create VaapiWrapper"; + return nullptr; + } + } DCHECK(vaapi_wrapper_); if (!video_frame) { LOG(ERROR) << "Video frame is nullptr";
diff --git a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.h b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.h index b218a51f..30b143f 100644 --- a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.h +++ b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.h
@@ -31,13 +31,15 @@ // VideoFrameMapper override. scoped_refptr<VideoFrame> MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const override; + int permissions) override; private: explicit VaapiDmaBufVideoFrameMapper(VideoPixelFormat format); + SEQUENCE_CHECKER(sequence_checker_); // Vaapi components for mapping. - const scoped_refptr<VaapiWrapper> vaapi_wrapper_; + scoped_refptr<VaapiWrapper> vaapi_wrapper_ + GUARDED_BY_CONTEXT(sequence_checker_); }; } // namespace media
diff --git a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc index 02e7b0df..bbec69e4 100644 --- a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc +++ b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc
@@ -115,37 +115,45 @@ base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiImageDecodeAcceleratorWorker.VAAPIError"); VaapiImageDecoderVector decoders; + gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles; auto jpeg_decoder = std::make_unique<VaapiJpegDecoder>(); - // TODO(crbug.com/974438): we can't advertise accelerated image decoding in - // AMD until we support VAAPI surfaces with multiple buffer objects. - if (VaapiWrapper::GetImplementationType() != VAImplementation::kMesaGallium && - jpeg_decoder->Initialize(uma_cb)) { + std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> + jpeg_decoder_supported_profile = VaapiJpegDecoder::GetSupportedProfile(); + if (jpeg_decoder_supported_profile && jpeg_decoder->Initialize(uma_cb)) { decoders.push_back(std::move(jpeg_decoder)); + supported_profiles.push_back(*jpeg_decoder_supported_profile); } auto webp_decoder = std::make_unique<VaapiWebPDecoder>(); - if (webp_decoder->Initialize(uma_cb)) + std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> + webp_decoder_supported_profile = VaapiWebPDecoder::GetSupportedProfile(); + if (webp_decoder_supported_profile && webp_decoder->Initialize(uma_cb)) { decoders.push_back(std::move(webp_decoder)); + supported_profiles.push_back(*webp_decoder_supported_profile); + } // If there are no decoders due to disabled flags or initialization failure, // return nullptr. if (decoders.empty()) return nullptr; - return base::WrapUnique( - new VaapiImageDecodeAcceleratorWorker(std::move(decoders))); + return base::WrapUnique(new VaapiImageDecodeAcceleratorWorker( + std::move(decoders), std::move(supported_profiles))); } VaapiImageDecodeAcceleratorWorker::VaapiImageDecodeAcceleratorWorker( - VaapiImageDecoderVector decoders) { + VaapiImageDecoderVector decoders, + gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles) + : supported_profiles_(std::move(supported_profiles)) { DETACH_FROM_SEQUENCE(io_sequence_checker_); decoder_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); DCHECK(decoder_task_runner_); - DCHECK(!decoders.empty()); + CHECK(!supported_profiles_.empty()); + CHECK(!decoders.empty()); + CHECK_EQ(decoders.size(), supported_profiles_.size()); for (auto& decoder : decoders) { - supported_profiles_.push_back(decoder->GetSupportedProfile()); const gpu::ImageDecodeAcceleratorType type = decoder->GetType(); decoders_[type] = std::move(decoder); }
diff --git a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h index 16d98de..c09acd0 100644 --- a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h +++ b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h
@@ -60,7 +60,9 @@ private: friend class VaapiImageDecodeAcceleratorWorkerTest; - explicit VaapiImageDecodeAcceleratorWorker(VaapiImageDecoderVector decoders); + VaapiImageDecodeAcceleratorWorker( + VaapiImageDecoderVector decoders, + gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles); VaapiImageDecoder* GetDecoderForImage( const std::vector<uint8_t>& encoded_data); @@ -68,7 +70,7 @@ // We delegate the decoding to the appropriate decoder in |decoders_| which // are used and destroyed on |decoder_task_runner_|. VaapiImageDecoderMap decoders_; - gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles_; + const gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles_; scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_; SEQUENCE_CHECKER(main_sequence_checker_);
diff --git a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker_unittest.cc b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker_unittest.cc index 2db0c4c7..68b6763 100644 --- a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker_unittest.cc +++ b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker_unittest.cc
@@ -106,11 +106,6 @@ } } - gpu::ImageDecodeAcceleratorSupportedProfile GetSupportedProfile() - const override { - return gpu::ImageDecodeAcceleratorSupportedProfile(); - } - MOCK_METHOD1(Initialize, bool(const ReportErrorToUMACB&)); MOCK_METHOD1(Decode, VaapiImageDecodeStatus(base::span<const uint8_t>)); MOCK_CONST_METHOD0(GetScopedVASurface, const ScopedVASurface*()); @@ -134,12 +129,21 @@ features::kVaapiWebPImageDecodeAcceleration} /* enabled_features */, {} /* disabled_features */); VaapiImageDecoderVector decoders; + gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles; + + auto fake_jpeg_profile = + GetFakeSupportedProfile(gpu::ImageDecodeAcceleratorType::kJpeg); + supported_profiles.push_back(fake_jpeg_profile); + auto fake_webp_profile = + GetFakeSupportedProfile(gpu::ImageDecodeAcceleratorType::kWebP); + supported_profiles.push_back(fake_webp_profile); + decoders.push_back(std::make_unique<StrictMock<MockVaapiImageDecoder>>( gpu::ImageDecodeAcceleratorType::kJpeg)); decoders.push_back(std::make_unique<StrictMock<MockVaapiImageDecoder>>( gpu::ImageDecodeAcceleratorType::kWebP)); - worker_ = base::WrapUnique( - new VaapiImageDecodeAcceleratorWorker(std::move(decoders))); + worker_ = base::WrapUnique(new VaapiImageDecodeAcceleratorWorker( + std::move(decoders), std::move(supported_profiles))); } VaapiImageDecodeAcceleratorWorkerTest( @@ -147,6 +151,13 @@ VaapiImageDecodeAcceleratorWorkerTest& operator=( const VaapiImageDecodeAcceleratorWorkerTest&) = delete; + gpu::ImageDecodeAcceleratorSupportedProfile GetFakeSupportedProfile( + gpu::ImageDecodeAcceleratorType type) { + gpu::ImageDecodeAcceleratorSupportedProfile profile; + profile.image_type = type; + return profile; + } + MockVaapiImageDecoder* GetJpegDecoder() const { auto result = worker_->decoders_.find(gpu::ImageDecodeAcceleratorType::kJpeg);
diff --git a/media/gpu/vaapi/vaapi_image_decoder.cc b/media/gpu/vaapi/vaapi_image_decoder.cc index 43ef6aa9..11e27df 100644 --- a/media/gpu/vaapi/vaapi_image_decoder.cc +++ b/media/gpu/vaapi/vaapi_image_decoder.cc
@@ -63,32 +63,6 @@ return scoped_va_context_and_surface_.get(); } -gpu::ImageDecodeAcceleratorSupportedProfile -VaapiImageDecoder::GetSupportedProfile() const { - if (!vaapi_wrapper_) { - DVLOGF(1) << "The VAAPI has not been initialized"; - return gpu::ImageDecodeAcceleratorSupportedProfile(); - } - - gpu::ImageDecodeAcceleratorSupportedProfile profile; - profile.image_type = GetType(); - DCHECK_NE(gpu::ImageDecodeAcceleratorType::kUnknown, profile.image_type); - - // Note that since |vaapi_wrapper_| was created successfully, we expect the - // following call to be successful. Hence the DCHECK. - const bool got_supported_resolutions = VaapiWrapper::GetSupportedResolutions( - va_profile_, VaapiWrapper::CodecMode::kDecode, - profile.min_encoded_dimensions, profile.max_encoded_dimensions); - DCHECK(got_supported_resolutions); - - // TODO(andrescj): Ideally, we would advertise support for all the formats - // supported by the driver. However, for now, we will only support exposing - // YUV 4:2:0 surfaces as DmaBufs. - DCHECK(VaapiWrapper::GetDecodeSupportedInternalFormats(va_profile_).yuv420); - profile.subsamplings.push_back(gpu::ImageDecodeAcceleratorSubsampling::k420); - return profile; -} - std::unique_ptr<NativePixmapAndSizeInfo> VaapiImageDecoder::ExportAsNativePixmapDmaBuf(VaapiImageDecodeStatus* status) { DCHECK(status);
diff --git a/media/gpu/vaapi/vaapi_image_decoder.h b/media/gpu/vaapi/vaapi_image_decoder.h index ac654dc..3c41c2b 100644 --- a/media/gpu/vaapi/vaapi_image_decoder.h +++ b/media/gpu/vaapi/vaapi_image_decoder.h
@@ -87,10 +87,6 @@ // returned by ExportAsNativePixmapDmaBuf() from YUV to RGB. virtual SkYUVColorSpace GetYUVColorSpace() const = 0; - // Returns the image profile supported by this decoder. - virtual gpu::ImageDecodeAcceleratorSupportedProfile GetSupportedProfile() - const; - // Exports the decoded data from the last Decode() call as a // gfx::NativePixmapDmaBuf. Returns nullptr on failure and sets *|status| to // the reason for failure. On success, the image decoder gives up ownership of
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.cc b/media/gpu/vaapi/vaapi_jpeg_decoder.cc index cfac370..1760b5e 100644 --- a/media/gpu/vaapi/vaapi_jpeg_decoder.cc +++ b/media/gpu/vaapi/vaapi_jpeg_decoder.cc
@@ -261,6 +261,34 @@ return SkYUVColorSpace::kJPEG_SkYUVColorSpace; } +// static +std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> +VaapiJpegDecoder::GetSupportedProfile() { + if (VaapiWrapper::GetImplementationType() == VAImplementation::kMesaGallium) { + // TODO(crbug.com/974438): we can't advertise accelerated image decoding in + // AMD until we support VAAPI surfaces with multiple buffer objects. + return std::nullopt; + } + + gpu::ImageDecodeAcceleratorSupportedProfile profile; + profile.image_type = gpu::ImageDecodeAcceleratorType::kJpeg; + + const bool got_supported_resolutions = VaapiWrapper::GetSupportedResolutions( + VAProfileJPEGBaseline, VaapiWrapper::CodecMode::kDecode, + profile.min_encoded_dimensions, profile.max_encoded_dimensions); + if (!got_supported_resolutions) { + return std::nullopt; + } + + // TODO(andrescj): Ideally, we would advertise support for all the formats + // supported by the driver. However, for now, we will only support exposing + // YUV 4:2:0 surfaces as DmaBufs. + CHECK(VaapiWrapper::GetDecodeSupportedInternalFormats(VAProfileJPEGBaseline) + .yuv420); + profile.subsamplings.push_back(gpu::ImageDecodeAcceleratorSubsampling::k420); + return profile; +} + std::unique_ptr<ScopedVAImage> VaapiJpegDecoder::GetImage( uint32_t preferred_image_fourcc, VaapiImageDecodeStatus* status) {
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.h b/media/gpu/vaapi/vaapi_jpeg_decoder.h index 1ba5e96..982e65e 100644 --- a/media/gpu/vaapi/vaapi_jpeg_decoder.h +++ b/media/gpu/vaapi/vaapi_jpeg_decoder.h
@@ -46,6 +46,10 @@ std::unique_ptr<ScopedVAImage> GetImage(uint32_t preferred_image_fourcc, VaapiImageDecodeStatus* status); + // Returns the supported image profile. + static std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> + GetSupportedProfile(); + private: friend class fuzzing::VaapiJpegDecoderWrapper;
diff --git a/media/gpu/vaapi/vaapi_webp_decoder.cc b/media/gpu/vaapi/vaapi_webp_decoder.cc index 11a96a9..1bc25262 100644 --- a/media/gpu/vaapi/vaapi_webp_decoder.cc +++ b/media/gpu/vaapi/vaapi_webp_decoder.cc
@@ -83,6 +83,27 @@ return SkYUVColorSpace::kRec601_SkYUVColorSpace; } +// static +std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> +VaapiWebPDecoder::GetSupportedProfile() { + gpu::ImageDecodeAcceleratorSupportedProfile profile; + profile.image_type = gpu::ImageDecodeAcceleratorType::kWebP; + + const bool got_supported_resolutions = VaapiWrapper::GetSupportedResolutions( + kWebPVAProfile, VaapiWrapper::CodecMode::kDecode, + profile.min_encoded_dimensions, profile.max_encoded_dimensions); + if (!got_supported_resolutions) { + return std::nullopt; + } + + // TODO(andrescj): Ideally, we would advertise support for all the formats + // supported by the driver. However, for now, we will only support exposing + // YUV 4:2:0 surfaces as DmaBufs. + CHECK(VaapiWrapper::GetDecodeSupportedInternalFormats(kWebPVAProfile).yuv420); + profile.subsamplings.push_back(gpu::ImageDecodeAcceleratorSubsampling::k420); + return profile; +} + VaapiImageDecodeStatus VaapiWebPDecoder::AllocateVASurfaceAndSubmitVABuffers( base::span<const uint8_t> encoded_image) { DCHECK(vaapi_wrapper_);
diff --git a/media/gpu/vaapi/vaapi_webp_decoder.h b/media/gpu/vaapi/vaapi_webp_decoder.h index 2a96492..024ef6e4 100644 --- a/media/gpu/vaapi/vaapi_webp_decoder.h +++ b/media/gpu/vaapi/vaapi_webp_decoder.h
@@ -24,6 +24,10 @@ gpu::ImageDecodeAcceleratorType GetType() const override; SkYUVColorSpace GetYUVColorSpace() const override; + // Returns the image profile supported. + static std::optional<gpu::ImageDecodeAcceleratorSupportedProfile> + GetSupportedProfile(); + private: // VaapiImageDecoder implementation. VaapiImageDecodeStatus AllocateVASurfaceAndSubmitVABuffers(
diff --git a/media/gpu/video_frame_mapper.cc b/media/gpu/video_frame_mapper.cc index 18d237a..0491c4a 100644 --- a/media/gpu/video_frame_mapper.cc +++ b/media/gpu/video_frame_mapper.cc
@@ -9,7 +9,7 @@ namespace media { scoped_refptr<VideoFrame> VideoFrameMapper::Map( scoped_refptr<const VideoFrame> video_frame, - int permissions) const { + int permissions) { return MapFrame(VideoFrameResource::CreateConst(std::move(video_frame)), permissions); }
diff --git a/media/gpu/video_frame_mapper.h b/media/gpu/video_frame_mapper.h index 0f6b55d0..f19cd1a 100644 --- a/media/gpu/video_frame_mapper.h +++ b/media/gpu/video_frame_mapper.h
@@ -31,12 +31,12 @@ // if needed. virtual scoped_refptr<VideoFrame> MapFrame( scoped_refptr<const FrameResource> video_frame, - int permissions) const = 0; + int permissions) = 0; // VideoFrame version of Map(). This wraps the VideoFrame in a FrameResource // and calls Map(scoped_refpr<FrameResource> ...). scoped_refptr<VideoFrame> Map(scoped_refptr<const VideoFrame> video_frame, - int permissions) const; + int permissions); // Returns the allowed pixel format of video frames on Map(). VideoPixelFormat pixel_format() const { return format_; }
diff --git a/media/gpu/windows/scoped_d3d_buffers_unittest.cc b/media/gpu/windows/scoped_d3d_buffers_unittest.cc index 64bc869..6ddf87f 100644 --- a/media/gpu/windows/scoped_d3d_buffers_unittest.cc +++ b/media/gpu/windows/scoped_d3d_buffers_unittest.cc
@@ -4,6 +4,7 @@ #include "media/gpu/windows/scoped_d3d_buffers.h" +#include "base/containers/heap_array.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -12,19 +13,20 @@ class MemoryBuffer : public ScopedD3DBuffer { public: - explicit MemoryBuffer(size_t size) : raw_data_(new uint8_t[size]) { - data_ = base::span<uint8_t>(raw_data_.get(), size); + explicit MemoryBuffer(size_t size) + : raw_data_(base::HeapArray<uint8_t>::Uninit(size)) { + data_ = raw_data_.as_span(); } bool Commit() override { - raw_data_.reset(); + raw_data_ = base::HeapArray<uint8_t>(); return true; } bool Commit(uint32_t) override { return Commit(); } private: - std::unique_ptr<uint8_t[]> raw_data_; + base::HeapArray<uint8_t> raw_data_; }; } // namespace
diff --git a/mojo/core/ipcz_api.cc b/mojo/core/ipcz_api.cc index 2c9d258d..0a31cf1 100644 --- a/mojo/core/ipcz_api.cc +++ b/mojo/core/ipcz_api.cc
@@ -9,6 +9,8 @@ #include "third_party/ipcz/include/ipcz/ipcz.h" #include "third_party/ipcz/src/api.h" +#include <vector> + namespace mojo::core { namespace {
diff --git a/mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc b/mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc index c5e87ca7..6517def 100644 --- a/mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc +++ b/mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc
@@ -12,7 +12,7 @@ mojo_base::BigBuffer StructTraits<mojo_base::mojom::RefCountedMemoryDataView, scoped_refptr<base::RefCountedMemory>>:: data(const scoped_refptr<base::RefCountedMemory>& in) { - return mojo_base::BigBuffer(base::make_span(in->front(), in->size())); + return mojo_base::BigBuffer(base::span(*in)); } // static
diff --git a/mojo/public/tools/bindings/generators/mojom_ts_generator.py b/mojo/public/tools/bindings/generators/mojom_ts_generator.py index 005d79b..e7fce5a4 100644 --- a/mojo/public/tools/bindings/generators/mojom_ts_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_ts_generator.py
@@ -88,6 +88,14 @@ mojom.INT32: "mojo.internal.Int32", mojom.UINT32: "mojo.internal.Uint32", mojom.FLOAT: "mojo.internal.Float", + mojom.NULLABLE_BOOL: "mojo.internal.Bool", + mojom.NULLABLE_INT8: "mojo.internal.Int8", + mojom.NULLABLE_UINT8: "mojo.internal.Uint8", + mojom.NULLABLE_INT16: "mojo.internal.Int16", + mojom.NULLABLE_UINT16: "mojo.internal.Uint16", + mojom.NULLABLE_INT32: "mojo.internal.Int32", + mojom.NULLABLE_UINT32: "mojo.internal.Uint32", + mojom.NULLABLE_FLOAT: "mojo.internal.Float", mojom.HANDLE: "mojo.internal.Handle", mojom.DCPIPE: "mojo.internal.Handle", mojom.DPPIPE: "mojo.internal.Handle", @@ -103,6 +111,9 @@ mojom.INT64: "mojo.internal.Int64", mojom.UINT64: "mojo.internal.Uint64", mojom.DOUBLE: "mojo.internal.Double", + mojom.NULLABLE_INT64: "mojo.internal.Int64", + mojom.NULLABLE_UINT64: "mojo.internal.Uint64", + mojom.NULLABLE_DOUBLE: "mojo.internal.Double", mojom.STRING: "mojo.internal.String", mojom.NULLABLE_STRING: "mojo.internal.String", } @@ -447,7 +458,7 @@ def _GetSpecType(self, kind): def get_spec(kind): if self._IsPrimitiveKind(kind): - return _kind_to_lite_js_type[mojom.EnsureUnnullable(kind)] + return _kind_to_lite_js_type[kind] if mojom.IsArrayKind(kind): return "mojo.internal.Array(%s, %s)" % (get_spec( kind.kind), "true" if mojom.IsNullableKind(kind.kind) else "false")
diff --git a/net/base/directory_listing.cc b/net/base/directory_listing.cc index f70f70c6..0cd2a56 100644 --- a/net/base/directory_listing.cc +++ b/net/base/directory_listing.cc
@@ -24,8 +24,9 @@ DLOG_IF(WARNING, !header) << "Missing resource: directory listing header"; std::string result; - if (header) - result.assign(header->front_as<char>(), header->size()); + if (header) { + result = base::as_string_view(*header); + } result.append("<script>start("); base::EscapeJSONString(title, true, &result);
diff --git a/net/base/features.cc b/net/base/features.cc index 80778051..c2deb0c9 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -453,6 +453,11 @@ /*name=*/"IpPrivacyAlwaysProxy", /*default_value=*/""}; +const base::FeatureParam<bool> kIpPrivacyFallbackToDirect{ + &kEnableIpProtectionProxy, + /*name=*/"IpPrivacyFallbackToDirect", + /*default_value=*/true}; + // Network-change migration requires NetworkHandle support, which are currently // only supported on Android (see // NetworkChangeNotifier::AreNetworkHandlesSupported).
diff --git a/net/base/features.h b/net/base/features.h index 506b3a5..bc0620b5 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -463,6 +463,10 @@ // functionality. NET_EXPORT extern const base::FeatureParam<std::string> kIpPrivacyAlwaysProxy; +// Fallback to direct when connections to IP protection proxies fail. This +// defaults to true and is intended for development of the QUIC functionality. +NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyFallbackToDirect; + // Whether QuicParams::migrate_sessions_on_network_change_v2 defaults to true or // false. This is needed as a workaround to set this value to true on Android // but not on WebView (until crbug.com/1430082 has been fixed).
diff --git a/net/cert/cert_status_flags.cc b/net/cert/cert_status_flags.cc index 700a78bf..97be1b9d 100644 --- a/net/cert/cert_status_flags.cc +++ b/net/cert/cert_status_flags.cc
@@ -33,8 +33,6 @@ return ERR_CERTIFICATE_TRANSPARENCY_REQUIRED; if (cert_status & CERT_STATUS_SYMANTEC_LEGACY) return ERR_CERT_SYMANTEC_LEGACY; - // CERT_STATUS_NON_UNIQUE_NAME is intentionally not mapped to an error. - // It is treated as just a warning and used to degrade the SSL UI. if (cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION) return ERR_CERT_NAME_CONSTRAINT_VIOLATION; if (cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM) @@ -45,6 +43,9 @@ return ERR_CERT_DATE_INVALID; if (cert_status & CERT_STATUS_VALIDITY_TOO_LONG) return ERR_CERT_VALIDITY_TOO_LONG; + if (cert_status & CERT_STATUS_NON_UNIQUE_NAME) { + return ERR_CERT_NON_UNIQUE_NAME; + } if (cert_status & CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; if (cert_status & CERT_STATUS_NO_REVOCATION_MECHANISM)
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index 90383f32..b84b0678 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc
@@ -577,17 +577,6 @@ rv = MapCertStatusToNetError(verify_result->cert_status); } - // Flag certificates from publicly-trusted CAs that are issued to intranet - // hosts. While the CA/Browser Forum Baseline Requirements (v1.1) permit - // these to be issued until 1 November 2015, they represent a real risk for - // the deployment of gTLDs and are being phased out ahead of the hard - // deadline. - if (verify_result->is_issued_by_known_root && IsHostnameNonUnique(hostname)) { - verify_result->cert_status |= CERT_STATUS_NON_UNIQUE_NAME; - // CERT_STATUS_NON_UNIQUE_NAME will eventually become a hard error. For - // now treat it as a warning and do not map it to an error return value. - } - // Flag certificates using too long validity periods. if (verify_result->is_issued_by_known_root && HasTooLongValidity(*cert)) { verify_result->cert_status |= CERT_STATUS_VALIDITY_TOO_LONG; @@ -595,6 +584,19 @@ rv = MapCertStatusToNetError(verify_result->cert_status); } + // Flag certificates from publicly-trusted CAs that are issued to intranet + // hosts. These are not allowed per the CA/Browser Forum requirements. + // + // Validity period is checked first just for testing convenience; there's not + // a strong security reason to let validity period vs non-unique names take + // precedence. + if (verify_result->is_issued_by_known_root && IsHostnameNonUnique(hostname)) { + verify_result->cert_status |= CERT_STATUS_NON_UNIQUE_NAME; + if (rv == OK) { + rv = MapCertStatusToNetError(verify_result->cert_status); + } + } + // Record a histogram for per-verification usage of root certs. if (rv == OK) { RecordTrustAnchorHistogram(verify_result->public_key_hashes,
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index 35a89cd..ea3ea7c 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -1603,7 +1603,7 @@ /*ocsp_response=*/std::string(), /*sct_list=*/std::string(), 0, &verify_result, NetLogWithSource()); - EXPECT_THAT(error, IsOk()); + EXPECT_THAT(error, IsError(ERR_CERT_NON_UNIQUE_NAME)); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); // However, if the CA is not well known, these should not be flagged:
diff --git a/net/cookies/cookie_partition_key.cc b/net/cookies/cookie_partition_key.cc index 40007c4..60dc22626 100644 --- a/net/cookies/cookie_partition_key.cc +++ b/net/cookies/cookie_partition_key.cc
@@ -28,6 +28,11 @@ return base::unexpected(message); } +std::string SerializeSchemefulSite(const SchemefulSite& site) { + return site.GetURL().SchemeIsFile() ? site.SerializeFileSiteWithHost() + : site.Serialize(); +} + } // namespace CookiePartitionKey::SerializedCookiePartitionKey::SerializedCookiePartitionKey( @@ -114,9 +119,7 @@ } return base::ok(SerializedCookiePartitionKey( - in->site_.GetURL().SchemeIsFile() ? in->site_.SerializeFileSiteWithHost() - : in->site_.Serialize(), - in->IsThirdParty())); + SerializeSchemefulSite(in->site_), in->IsThirdParty())); } std::optional<CookiePartitionKey> CookiePartitionKey::FromNetworkIsolationKey( @@ -164,7 +167,8 @@ } base::expected<CookiePartitionKey, std::string> key = DeserializeInternal( - top_level_site, BoolToAncestorChainBit(has_cross_site_ancestor)); + top_level_site, BoolToAncestorChainBit(has_cross_site_ancestor), + ParsingMode::kStrict); if (!key.has_value()) { DLOG(WARNING) << key.error(); } @@ -181,7 +185,8 @@ } base::expected<CookiePartitionKey, std::string> key = DeserializeInternal( - top_level_site, BoolToAncestorChainBit(has_cross_site_ancestor)); + top_level_site, BoolToAncestorChainBit(has_cross_site_ancestor), + ParsingMode::kLoose); if (!key.has_value()) { return WarnAndCreateUnexpected(key.error()); } @@ -191,11 +196,16 @@ base::expected<CookiePartitionKey, std::string> CookiePartitionKey::DeserializeInternal( const std::string& top_level_site, - CookiePartitionKey::AncestorChainBit has_cross_site_ancestor) { + CookiePartitionKey::AncestorChainBit has_cross_site_ancestor, + CookiePartitionKey::ParsingMode parsing_mode) { auto schemeful_site = SchemefulSite::Deserialize(top_level_site); if (schemeful_site.opaque()) { return WarnAndCreateUnexpected( "Cannot deserialize opaque origin to CookiePartitionKey"); + } else if (parsing_mode == ParsingMode::kStrict && + SerializeSchemefulSite(schemeful_site) != top_level_site) { + return WarnAndCreateUnexpected( + "Cannot deserialize malformed top_level_site to CookiePartitionKey"); } return base::ok(CookiePartitionKey(schemeful_site, std::nullopt, has_cross_site_ancestor));
diff --git a/net/cookies/cookie_partition_key.h b/net/cookies/cookie_partition_key.h index 36dc2064..1e1b1798 100644 --- a/net/cookies/cookie_partition_key.h +++ b/net/cookies/cookie_partition_key.h
@@ -175,6 +175,18 @@ } private: + // Used by DeserializeInternal to determine how strict the context should be + // about inconsistencies in the input. + enum class ParsingMode { + // The top_level_site string must be serialized exactly as a SchemefulSite + // would be. + // Use this when reading from storage. + kStrict = 0, + // The top_level_site string must be coercible to a SchemefulSite. + // Use this for user input. + kLoose = 1, + }; + explicit CookiePartitionKey(const SchemefulSite& site, std::optional<base::UnguessableToken> nonce, AncestorChainBit ancestor_chain_bit); @@ -186,7 +198,8 @@ [[nodiscard]] static base::expected<CookiePartitionKey, std::string> DeserializeInternal( const std::string& top_level_site, - CookiePartitionKey::AncestorChainBit has_cross_site_ancestor); + CookiePartitionKey::AncestorChainBit has_cross_site_ancestor, + CookiePartitionKey::ParsingMode parsing_mode); AncestorChainBit MaybeAncestorChainBit() const;
diff --git a/net/cookies/cookie_partition_key_fuzzer.cc b/net/cookies/cookie_partition_key_fuzzer.cc index a0f4162..671298b 100644 --- a/net/cookies/cookie_partition_key_fuzzer.cc +++ b/net/cookies/cookie_partition_key_fuzzer.cc
@@ -21,19 +21,59 @@ if (!url.is_valid()) return 0; - std::optional<CookiePartitionKey> partition_key = - std::make_optional(CookiePartitionKey::FromURLForTesting(url)); + bool has_cross_site_ancestor = data_provider.ConsumeBool(); + CookiePartitionKey::AncestorChainBit ancestor_chain_bit = + has_cross_site_ancestor ? CookiePartitionKey::AncestorChainBit::kCrossSite + : CookiePartitionKey::AncestorChainBit::kSameSite; - bool is_opaque = url::Origin::Create(url).opaque(); - CHECK_NE(is_opaque, CookiePartitionKey::Serialize(partition_key).has_value()); + // Unlike FromURLForTesting and FromUntrustedInput, FromStorage requires the + // top_level_site string passed in be formatted exactly as a SchemefulSite + // would serialize it. Unlike FromURLForTesting, FromUntrustedInput and + // FromStorage require the top_level_site not be opaque. + base::expected<std::optional<CookiePartitionKey>, std::string> + partition_key_from_string_strict = + CookiePartitionKey::FromStorage(url_str, has_cross_site_ancestor); + base::expected<CookiePartitionKey, std::string> + partition_key_from_string_loose = CookiePartitionKey::FromUntrustedInput( + url_str, has_cross_site_ancestor); + CookiePartitionKey partition_key_from_url = + CookiePartitionKey::FromURLForTesting(url, ancestor_chain_bit); - CHECK_NE(is_opaque, CookiePartitionKey::FromUntrustedInput( - url_str, partition_key->IsThirdParty()) - .has_value()); - - if (!is_opaque) { - CHECK(std::make_optional(CookiePartitionKey::FromURLForTesting(url)) == - partition_key); + if (partition_key_from_string_strict.has_value() && + partition_key_from_string_strict.value().has_value()) { + // If we can deserialize from string while being strict the three keys + // should be identical. + CHECK_EQ(**partition_key_from_string_strict, partition_key_from_url); + CHECK_EQ(**partition_key_from_string_strict, + *partition_key_from_string_loose); + // This implies we can re-serialize. + base::expected<CookiePartitionKey::SerializedCookiePartitionKey, + std::string> + serialized_partition_key = + CookiePartitionKey::Serialize(**partition_key_from_string_strict); + CHECK(serialized_partition_key.has_value()); + // The serialization should match the initial values. + CHECK_EQ(serialized_partition_key->TopLevelSite(), url_str); + CHECK_EQ(serialized_partition_key->has_cross_site_ancestor(), + has_cross_site_ancestor); + } else if (partition_key_from_string_loose.has_value()) { + // If we can deserialize from string while being loose then two keys + // should be identical. + CHECK_EQ(*partition_key_from_string_loose, partition_key_from_url); + // This implies we can re-serialize. + base::expected<CookiePartitionKey::SerializedCookiePartitionKey, + std::string> + serialized_partition_key = + CookiePartitionKey::Serialize(*partition_key_from_string_loose); + // The serialization should match the initial values. + CHECK_EQ(serialized_partition_key->TopLevelSite(), + SchemefulSite(url).Serialize()); + CHECK_EQ(serialized_partition_key->has_cross_site_ancestor(), + has_cross_site_ancestor); + } else { + // If we cannot deserialize from string at all then top_level_site must be + // opaque. + CHECK(partition_key_from_url.site().opaque()); } return 0;
diff --git a/net/cookies/cookie_partition_key_unittest.cc b/net/cookies/cookie_partition_key_unittest.cc index f453a1e..2c6f6c65 100644 --- a/net/cookies/cookie_partition_key_unittest.cc +++ b/net/cookies/cookie_partition_key_unittest.cc
@@ -14,6 +14,8 @@ namespace net { +using enum CookiePartitionKey::AncestorChainBit; + class CookiePartitionKeyTest : public testing::TestWithParam<bool> { protected: // testing::Test @@ -43,14 +45,15 @@ "", true, CookiePartitionKey::FromURLForTesting(GURL(""))}, /*invalid site*/ {"Invalid", true, std::nullopt}, + /*malformed site*/ + {"https://toplevelsite.com/", true, std::nullopt}, /*valid site: cross site*/ {"https://toplevelsite.com", true, CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"))}, /*valid site: same site*/ {"https://toplevelsite.com", false, - CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"), - CookiePartitionKey::AncestorChainBit::kSameSite)}}; + CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"), + kSameSite)}}; for (const auto& tc : cases) { base::expected<std::optional<CookiePartitionKey>, std::string> got = CookiePartitionKey::FromStorage(tc.top_level_site, tc.third_party); @@ -65,82 +68,78 @@ TEST_P(CookiePartitionKeyTest, TestFromUntrustedInput) { const std::string kFullURL = "https://subdomain.toplevelsite.com/index.html"; const std::string kValidSite = "https://toplevelsite.com"; + struct Output { + bool third_party; + }; struct { std::string top_level_site; CookiePartitionKey::AncestorChainBit has_cross_site_ancestor; - bool partition_key_created; - bool expected_third_party; + std::optional<Output> expected_output; } cases[] = { {/*empty site*/ - "", CookiePartitionKey::AncestorChainBit::kCrossSite, false, true}, + "", kCrossSite, std::nullopt}, {/*empty site : same site ancestor*/ - "", CookiePartitionKey::AncestorChainBit::kSameSite, false, false}, + "", kSameSite, std::nullopt}, {/*valid site*/ - kValidSite, CookiePartitionKey::AncestorChainBit::kCrossSite, true, - true}, + kValidSite, kCrossSite, Output{true}}, {/*valid site: same site ancestor*/ - kValidSite, CookiePartitionKey::AncestorChainBit::kSameSite, true, - false}, + kValidSite, kSameSite, Output{false}}, + {/*valid site with extra slash: same site ancestor*/ + kValidSite + "/", kSameSite, Output{false}}, {/*invalid site (missing scheme)*/ - "toplevelsite.com", CookiePartitionKey::AncestorChainBit::kCrossSite, - false, true}, + "toplevelsite.com", kCrossSite, std::nullopt}, {/*invalid site (missing scheme): same site ancestor*/ - "toplevelsite.com", CookiePartitionKey::AncestorChainBit::kSameSite, - false, false}, + "toplevelsite.com", kSameSite, std::nullopt}, {/*invalid site*/ - "abc123foobar!!", CookiePartitionKey::AncestorChainBit::kCrossSite, - false, true}, + "abc123foobar!!", kCrossSite, std::nullopt}, {/*invalid site: same site ancestor*/ - "abc123foobar!!", CookiePartitionKey::AncestorChainBit::kSameSite, false, - false}, + "abc123foobar!!", kSameSite, std::nullopt}, }; for (const auto& tc : cases) { base::expected<CookiePartitionKey, std::string> got = CookiePartitionKey::FromUntrustedInput( - tc.top_level_site, - tc.has_cross_site_ancestor == - CookiePartitionKey::AncestorChainBit::kCrossSite); - EXPECT_EQ(got.has_value(), tc.partition_key_created); - if (tc.partition_key_created) { + tc.top_level_site, tc.has_cross_site_ancestor == kCrossSite); + EXPECT_EQ(got.has_value(), tc.expected_output.has_value()); + if (tc.expected_output.has_value()) { EXPECT_EQ(got->site().Serialize(), kValidSite); - EXPECT_EQ(got->IsThirdParty(), tc.expected_third_party); + EXPECT_EQ(got->IsThirdParty(), tc.expected_output->third_party); } } } TEST_P(CookiePartitionKeyTest, Serialization) { base::UnguessableToken nonce = base::UnguessableToken::Create(); + struct Output { + std::string top_level_site; + bool cross_site; + }; struct { std::optional<CookiePartitionKey> input; - std::string expected_output_top_level_site; - bool expected_success; - bool expected_cross_site; + std::optional<Output> expected_output; } cases[] = { // No partition key - {std::nullopt, kEmptyCookiePartitionKey, true, true}, + {std::nullopt, Output{kEmptyCookiePartitionKey, true}}, // Partition key present {CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")), - "https://toplevelsite.com", true, true}, + Output{"https://toplevelsite.com", true}}, // Local file URL {CookiePartitionKey::FromURLForTesting(GURL("file:///path/to/file.txt")), - "file://", true, true}, + Output{"file://", true}}, // File URL with host {CookiePartitionKey::FromURLForTesting( GURL("file://toplevelsite.com/path/to/file.pdf")), - "file://toplevelsite.com", true, true}, + Output{"file://toplevelsite.com", true}}, // Opaque origin - {CookiePartitionKey::FromURLForTesting(GURL()), "", false, true}, + {CookiePartitionKey::FromURLForTesting(GURL()), std::nullopt}, // AncestorChain::kSameSite - {CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"), - CookiePartitionKey::AncestorChainBit::kSameSite, std::nullopt), - "https://toplevelsite.com", true, false}, + {CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"), + kSameSite, std::nullopt), + Output{"https://toplevelsite.com", false}}, // AncestorChain::kCrossSite - {CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"), - CookiePartitionKey::AncestorChainBit::kCrossSite, std::nullopt), - "https://toplevelsite.com", true, true}, + {CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"), + kCrossSite, std::nullopt), + Output{"https://toplevelsite.com", true}}, // With nonce {CookiePartitionKey::FromNetworkIsolationKey( NetworkIsolationKey(SchemefulSite(GURL("https://toplevelsite.com")), @@ -148,21 +147,21 @@ nonce), SiteForCookies::FromUrl(GURL::EmptyGURL()), SchemefulSite(GURL("https://toplevelsite.com"))), - "", false, true}, + std::nullopt}, // Same site no nonce from NIK {CookiePartitionKey::FromNetworkIsolationKey( NetworkIsolationKey(SchemefulSite(GURL("https://toplevelsite.com")), SchemefulSite(GURL("https://toplevelsite.com"))), SiteForCookies::FromUrl(GURL("https://toplevelsite.com")), SchemefulSite(GURL("https://toplevelsite.com"))), - "https://toplevelsite.com", true, false}, + Output{"https://toplevelsite.com", false}}, // Different request_site results in cross site ancestor {CookiePartitionKey::FromNetworkIsolationKey( NetworkIsolationKey(SchemefulSite(GURL("https://toplevelsite.com")), SchemefulSite(GURL("https://toplevelsite.com"))), SiteForCookies::FromUrl(GURL("https://toplevelsite.com")), SchemefulSite(GURL("https://differentOrigin.com"))), - "https://toplevelsite.com", true, true}, + Output{"https://toplevelsite.com", true}}, // Same site with nonce from NIK {CookiePartitionKey::FromNetworkIsolationKey( NetworkIsolationKey(SchemefulSite(GURL("https://toplevelsite.com")), @@ -170,11 +169,11 @@ nonce), SiteForCookies::FromUrl(GURL("https://toplevelsite.com")), SchemefulSite(GURL("https://toplevelsite.com"))), - "", false, true}, + std::nullopt}, // Invalid partition key {std::make_optional( CookiePartitionKey::FromURLForTesting(GURL("abc123foobar!!"))), - "", false, true}, + std::nullopt}, }; for (const auto& tc : cases) { @@ -182,12 +181,12 @@ std::string> got = CookiePartitionKey::Serialize(tc.input); - EXPECT_EQ(tc.expected_success, got.has_value()); + EXPECT_EQ(tc.expected_output.has_value(), got.has_value()); if (got.has_value()) { // TODO (crbug.com/41486025) once ancestor chain bit is implemented update // test to check bit's value. - EXPECT_EQ(tc.expected_output_top_level_site, got->TopLevelSite()); - EXPECT_EQ(tc.expected_cross_site, got->has_cross_site_ancestor()); + EXPECT_EQ(tc.expected_output->top_level_site, got->TopLevelSite()); + EXPECT_EQ(tc.expected_output->cross_site, got->has_cross_site_ancestor()); } } } @@ -213,30 +212,26 @@ SiteForCookies::FromUrl(GURL::EmptyGURL()), SchemefulSite(kTopLevelSite)}, {"WithNonce", NetworkIsolationKey(kTopLevelSite, kCookieSite, kNonce), - CookiePartitionKey::FromURLForTesting( - kCookieSite.GetURL(), - CookiePartitionKey::AncestorChainBit::kCrossSite, kNonce), + CookiePartitionKey::FromURLForTesting(kCookieSite.GetURL(), kCrossSite, + kNonce), SiteForCookies::FromUrl(GURL::EmptyGURL()), SchemefulSite(kTopLevelSite)}, {"WithCrossSiteAncestorSameSite", NetworkIsolationKey(kTopLevelSite, kTopLevelSite), - CookiePartitionKey::FromURLForTesting( - kTopLevelSite.GetURL(), - CookiePartitionKey::AncestorChainBit::kSameSite, std::nullopt), + CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL(), kSameSite, + std::nullopt), SiteForCookies::FromUrl(GURL(kTopLevelSite.GetURL())), SchemefulSite(kTopLevelSite)}, {"Nonced first party NIK results in kCrossSite partition key", NetworkIsolationKey(kTopLevelSite, kTopLevelSite, kNonce), - CookiePartitionKey::FromURLForTesting( - kTopLevelSite.GetURL(), - CookiePartitionKey::AncestorChainBit::kCrossSite, kNonce), + CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL(), kCrossSite, + kNonce), SiteForCookies::FromUrl(GURL(kTopLevelSite.GetURL())), SchemefulSite(kTopLevelSite)}, {"WithCrossSiteAncestorNotSameSite", NetworkIsolationKey(kTopLevelSite, kTopLevelSite), - CookiePartitionKey::FromURLForTesting( - kTopLevelSite.GetURL(), - CookiePartitionKey::AncestorChainBit::kCrossSite, std::nullopt), + CookiePartitionKey::FromURLForTesting(kTopLevelSite.GetURL(), kCrossSite, + std::nullopt), SiteForCookies::FromUrl(GURL::EmptyGURL()), kCookieSite}}; base::test::ScopedFeatureList feature_list; @@ -265,21 +260,16 @@ const std::optional<base::UnguessableToken> nonce; const CookiePartitionKey::AncestorChainBit ancestor_chain_bit; } test_cases[] = { - {GURL("https://foo.com"), std::nullopt, - CookiePartitionKey::AncestorChainBit::kCrossSite}, - {GURL("https://foo.com"), std::nullopt, - CookiePartitionKey::AncestorChainBit::kSameSite}, - {GURL(), std::nullopt, CookiePartitionKey::AncestorChainBit::kCrossSite}, - {GURL("https://foo.com"), base::UnguessableToken::Create(), - CookiePartitionKey::AncestorChainBit::kCrossSite}}; + {GURL("https://foo.com"), std::nullopt, kCrossSite}, + {GURL("https://foo.com"), std::nullopt, kSameSite}, + {GURL(), std::nullopt, kCrossSite}, + {GURL("https://foo.com"), base::UnguessableToken::Create(), kCrossSite}}; for (const auto& test_case : test_cases) { auto want = CookiePartitionKey::FromURLForTesting( test_case.url, test_case.ancestor_chain_bit, test_case.nonce); auto got = CookiePartitionKey::FromWire( - want.site(), - want.IsThirdParty() ? CookiePartitionKey::AncestorChainBit::kCrossSite - : CookiePartitionKey::AncestorChainBit::kSameSite, + want.site(), want.IsThirdParty() ? kCrossSite : kSameSite, want.nonce()); EXPECT_EQ(want, got); EXPECT_FALSE(got.from_script()); @@ -292,23 +282,17 @@ const std::optional<base::UnguessableToken> nonce = std::nullopt; const CookiePartitionKey::AncestorChainBit ancestor_chain_bit; } test_cases[] = { - {GURL("https://foo.com"), std::nullopt, - CookiePartitionKey::AncestorChainBit::kCrossSite}, - {GURL("https://foo.com"), std::nullopt, - CookiePartitionKey::AncestorChainBit::kSameSite}, - {GURL(), std::nullopt, CookiePartitionKey::AncestorChainBit::kCrossSite}, - {GURL("https://foo.com"), base::UnguessableToken::Create(), - CookiePartitionKey::AncestorChainBit::kCrossSite}}; + {GURL("https://foo.com"), std::nullopt, kCrossSite}, + {GURL("https://foo.com"), std::nullopt, kSameSite}, + {GURL(), std::nullopt, kCrossSite}, + {GURL("https://foo.com"), base::UnguessableToken::Create(), kCrossSite}}; for (const auto& test_case : test_cases) { auto want = CookiePartitionKey::FromURLForTesting( test_case.url, test_case.ancestor_chain_bit, test_case.nonce); std::optional<CookiePartitionKey> got = CookiePartitionKey::FromStorageKeyComponents( - want.site(), - want.IsThirdParty() - ? CookiePartitionKey::AncestorChainBit::kCrossSite - : CookiePartitionKey::AncestorChainBit::kSameSite, + want.site(), want.IsThirdParty() ? kCrossSite : kSameSite, want.nonce()); EXPECT_EQ(got, want); } @@ -352,17 +336,13 @@ TEST_P(CookiePartitionKeyTest, Equality_WithAncestorChain) { CookiePartitionKey key1 = CookiePartitionKey::FromURLForTesting( - GURL("https://foo.com"), CookiePartitionKey::AncestorChainBit::kSameSite, - std::nullopt); + GURL("https://foo.com"), kSameSite, std::nullopt); CookiePartitionKey key2 = CookiePartitionKey::FromURLForTesting( - GURL("https://foo.com"), CookiePartitionKey::AncestorChainBit::kCrossSite, - std::nullopt); + GURL("https://foo.com"), kCrossSite, std::nullopt); EXPECT_EQ((key1 == key2), !AncestorChainBitEnabled()); - EXPECT_EQ(key1, - CookiePartitionKey::FromURLForTesting( - GURL("https://foo.com"), - CookiePartitionKey::AncestorChainBit::kSameSite, std::nullopt)); + EXPECT_EQ(key1, CookiePartitionKey::FromURLForTesting( + GURL("https://foo.com"), kSameSite, std::nullopt)); } TEST_P(CookiePartitionKeyTest, Equality_WithNonce) {
diff --git a/net/http/http_proxy_connect_job.cc b/net/http/http_proxy_connect_job.cc index becb37b..3f9d2a02 100644 --- a/net/http/http_proxy_connect_job.cc +++ b/net/http/http_proxy_connect_job.cc
@@ -30,6 +30,7 @@ #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" #include "net/nqe/network_quality_estimator.h" +#include "net/quic/quic_context.h" #include "net/quic/quic_http_utils.h" #include "net/quic/quic_proxy_client_socket.h" #include "net/quic/quic_session_key.h" @@ -725,9 +726,9 @@ quic_session_request_ = std::make_unique<QuicSessionRequest>( common_connect_job_params()->quic_session_pool); - // Use default QUIC version, which is the version listed supported version. - quic::ParsedQuicVersion quic_version = - common_connect_job_params()->quic_supported_versions->front(); + // Select the default QUIC version for the session to the proxy, since there + // is no DNS or Alt-Svc information to use. + quic::ParsedQuicVersion quic_version = SupportedQuicVersionForProxying(); // The QuicSessionRequest will handle connecting to any proxies earlier in the // chain to this one, but expects a ProxyChain containing only QUIC proxies.
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index c171c7dde..14508ee 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -814,7 +814,7 @@ // Create an alternative job if alternative service is set up for this domain, // but only if we'll be speaking directly to the server, since QUIC through - // proxies is not supported. + // proxies is not supported. TODO(https://crbug.com/324534606): allow this. if (proxy_info_.is_direct()) { alternative_service_info_ = GetAlternativeServiceInfoFor( http_request_info_url_, request_info_, delegate_, stream_type_); @@ -825,6 +825,9 @@ SelectQuicVersion(alternative_service_info_.advertised_versions()); DCHECK_NE(quic_version, quic::ParsedQuicVersion::Unsupported()); } + // Getting ALPN for H3 from DNS has a lot of preconditions. Among them: + // - proxied connections perform DNS on the proxy, so they can't get supported + // ALPNs from DNS const bool dns_alpn_h3_job_enabled = !HttpStreamFactory::Job::OriginToForceQuicOn( *session_->context().quic_context->params(), destination) && @@ -832,7 +835,7 @@ session_->params().use_dns_https_svcb_alpn && base::EqualsCaseInsensitiveASCII(origin_url_.scheme(), url::kHttpsScheme) && - session_->IsQuicEnabled() && + session_->IsQuicEnabled() && proxy_info_.is_direct() && !session_->http_server_properties()->IsAlternativeServiceBroken( GetAlternativeServiceForDnsJob(origin_url_), request_info_.network_anonymization_key);
diff --git a/net/log/trace_net_log_observer_unittest.cc b/net/log/trace_net_log_observer_unittest.cc index c29858ed..a6ae18e 100644 --- a/net/log/trace_net_log_observer_unittest.cc +++ b/net/log/trace_net_log_observer_unittest.cc
@@ -124,7 +124,7 @@ bool has_more_events) { DCHECK(trace_events_.empty()); trace_buffer_.Start(); - trace_buffer_.AddFragment(events_str->data()); + trace_buffer_.AddFragment(events_str->as_string()); trace_buffer_.Finish(); std::optional<base::Value> trace_value;
diff --git a/net/quic/quic_context.h b/net/quic/quic_context.h index c50ae9e..bf8e269 100644 --- a/net/quic/quic_context.h +++ b/net/quic/quic_context.h
@@ -28,6 +28,17 @@ return quic::ParsedQuicVersionVector{quic::ParsedQuicVersion::RFCv1()}; } +// Return the QUIC version to be used for connections to proxies, for which +// there is currently no other way to determine QUIC version. +inline NET_EXPORT_PRIVATE quic::ParsedQuicVersion +SupportedQuicVersionForProxying() { + // Assume that all QUIC proxies use RFCv1, as the current support for proxy + // configuration does not allow any way to indicate what version they + // support. RFCv1 is commonly supported and is valid for IP Protection + // proxies, but this may not be true more broadly. + return quic::ParsedQuicVersion::RFCv1(); +} + // Obsolete QUIC supported versions are versions that are supported by the // QUIC shared code but that Chrome refuses to use because modern clients // should only use versions at least as recent as the oldest default version.
diff --git a/net/quic/quic_session_pool_proxy_job.cc b/net/quic/quic_session_pool_proxy_job.cc index 7a666883..fec1fb7 100644 --- a/net/quic/quic_session_pool_proxy_job.cc +++ b/net/quic/quic_session_pool_proxy_job.cc
@@ -13,6 +13,7 @@ #include "net/base/tracing.h" #include "net/log/net_log_with_source.h" #include "net/quic/address_utils.h" +#include "net/quic/quic_context.h" #include "net/quic/quic_crypto_client_config_handle.h" #include "net/quic/quic_http_stream.h" #include "net/quic/quic_session_pool.h" @@ -23,7 +24,7 @@ QuicSessionPool::ProxyJob::ProxyJob( QuicSessionPool* pool, - quic::ParsedQuicVersion quic_version, + quic::ParsedQuicVersion target_quic_version, const QuicSessionAliasKey& key, NetworkTrafficAnnotationTag proxy_annotation_tag, const HttpUserAgentSettings* http_user_agent_settings, @@ -41,11 +42,16 @@ NetLogSourceType::QUIC_SESSION_POOL_PROXY_JOB)), io_callback_(base::BindRepeating(&QuicSessionPool::ProxyJob::OnIOComplete, base::Unretained(this))), - quic_version_(quic_version), + target_quic_version_(target_quic_version), proxy_annotation_tag_(proxy_annotation_tag), cert_verify_flags_(cert_verify_flags), http_user_agent_settings_(http_user_agent_settings) { DCHECK(!Job::key().session_key().proxy_chain().is_direct()); + // The job relies on the the proxy to resolve DNS for the destination, so + // cannot determine protocol information from DNS. We must know the QUIC + // version already. + CHECK(target_quic_version.IsKnown()) + << "Cannot make QUIC proxy connections without a known QUIC version"; } QuicSessionPool::ProxyJob::~ProxyJob() = default; @@ -157,9 +163,13 @@ NetLogEventType::QUIC_SESSION_POOL_PROXY_JOB_CREATE_PROXY_SESSION, "destination", destination.Serialize()); + // Select the default QUIC version for the session to the proxy, since there + // is no DNS or Alt-Svc information to use. + quic::ParsedQuicVersion quic_version = SupportedQuicVersionForProxying(); + proxy_session_request_ = std::make_unique<QuicSessionRequest>(pool_); return proxy_session_request_->Request( - destination, quic_version_, proxy_chain_prefix, proxy_annotation_tag_, + destination, quic_version, proxy_chain_prefix, proxy_annotation_tag_, http_user_agent_settings_.get(), SessionUsage::kProxy, session_key.privacy_mode(), priority(), session_key.socket_tag(), session_key.network_anonymization_key(), session_key.secure_dns_policy(), @@ -221,8 +231,9 @@ } session_attempt_ = std::make_unique<SessionAttempt>( - this, std::move(local_address), std::move(peer_address), quic_version_, - cert_verify_flags_, std::move(proxy_stream_), http_user_agent_settings_); + this, std::move(local_address), std::move(peer_address), + target_quic_version_, cert_verify_flags_, std::move(proxy_stream_), + http_user_agent_settings_); return session_attempt_->Start( base::BindOnce(&ProxyJob::OnSessionAttemptComplete, GetWeakPtr()));
diff --git a/net/quic/quic_session_pool_proxy_job.h b/net/quic/quic_session_pool_proxy_job.h index 1a2f7f02..33f69b90 100644 --- a/net/quic/quic_session_pool_proxy_job.h +++ b/net/quic/quic_session_pool_proxy_job.h
@@ -23,7 +23,7 @@ class QuicSessionPool::ProxyJob : public QuicSessionPool::Job { public: ProxyJob(QuicSessionPool* pool, - quic::ParsedQuicVersion quic_version, + quic::ParsedQuicVersion target_quic_version, const QuicSessionAliasKey& key, NetworkTrafficAnnotationTag proxy_annotation_tag, const HttpUserAgentSettings* http_user_agent_settings, @@ -68,9 +68,10 @@ std::unique_ptr<QuicChromiumClientSession::Handle> proxy_session_; std::unique_ptr<QuicChromiumClientStream::Handle> proxy_stream_; NetErrorDetails net_error_details_; - quic::ParsedQuicVersion quic_version_; - quic::ParsedQuicVersion quic_version_used_ = - quic::ParsedQuicVersion::Unsupported(); + + // The QUIC version for the tunneled session created by this job. + quic::ParsedQuicVersion target_quic_version_; + NetworkTrafficAnnotationTag proxy_annotation_tag_; const int cert_verify_flags_; raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_;
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn index 14d5fd0..e733694 100644 --- a/pdf/BUILD.gn +++ b/pdf/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/features.gni") import("//pdf/features.gni") import("//ppapi/buildflags/buildflags.gni") +import("//services/screen_ai/buildflags/features.gni") import("//testing/libfuzzer/fuzzer_test.gni") import("//testing/test.gni") import("//third_party/pdfium/pdfium.gni") @@ -21,6 +22,7 @@ header = "buildflags.h" flags = [ "ENABLE_INK=$enable_ink", + "ENABLE_PDF_INK2=$enable_pdf_ink2", "ENABLE_PDF=$enable_pdf", ] } @@ -46,6 +48,7 @@ ":internal", "//base", "//build:chromeos_buildflags", + "//services/screen_ai/buildflags", "//ui/gfx/geometry", ] } @@ -57,6 +60,8 @@ public = [ "pdf_features.h" ] + public_deps = [ ":buildflags" ] + deps = [ "//base", "//build:chromeos_buildflags", @@ -112,6 +117,8 @@ "pdfium/pdfium_form_filler.h", "pdfium/pdfium_mem_buffer_file_write.cc", "pdfium/pdfium_mem_buffer_file_write.h", + "pdfium/pdfium_ocr.cc", + "pdfium/pdfium_ocr.h", "pdfium/pdfium_page.cc", "pdfium/pdfium_page.h", "pdfium/pdfium_permissions.cc", @@ -154,6 +161,7 @@ "//gin", "//pdf/loader", "//printing", + "//services/screen_ai/buildflags", "//third_party/blink/public:blink_headers", "//third_party/blink/public/common:headers", "//third_party/icu", @@ -181,6 +189,17 @@ "flatten_pdf_result.h", ] } + + if (enable_screen_ai_service) { + sources += [ + "pdfium/pdfium_searchify.cc", + "pdfium/pdfium_searchify.h", + "pdfium/pdfium_searchify_font.cc", + "pdfium/pdfium_searchify_font.h", + ] + + public_deps += [ "//services/screen_ai/public/mojom" ] + } } source_set("assert_enums") { @@ -277,6 +296,10 @@ "//ui/gfx/range", "//v8", ] + + if (enable_pdf_ink2) { + deps += [ "//pdf/ink" ] + } } source_set("pdf_test_utils") {
diff --git a/pdf/DEPS b/pdf/DEPS index 969ef6f..f4f6626 100644 --- a/pdf/DEPS +++ b/pdf/DEPS
@@ -6,6 +6,9 @@ "+net", "+printing", "+services/network/public/mojom/referrer_policy.mojom-shared.h", + "+services/screen_ai/buildflags", + "+services/screen_ai/public/mojom/screen_ai_service.mojom.h", + "+services/screen_ai/public/mojom/screen_ai_service.mojom-forward.h", "+third_party/blink/public", "+third_party/skia/include/core", "+ui/base",
diff --git a/pdf/features.gni b/pdf/features.gni index 88828d4..e89dcbd7 100644 --- a/pdf/features.gni +++ b/pdf/features.gni
@@ -10,12 +10,21 @@ # disabled. declare_args() { + enable_pdf = !is_android && !is_ios && !is_castos && !is_fuchsia +} + +declare_args() { # Enable ink libraries provided by the ChromeOS media app dependency. # # This argument indicates whether the ink libraries provided by the ChromeOS # media app dependency is enabled. It also determines whether the annotation - # feature is enabled for the PDF viewer. + # feature is enabled for the PDF Viewer on Chrome OS. enable_ink = enable_cros_media_app - enable_pdf = !is_android && !is_ios && !is_castos && !is_fuchsia + # Enable the next generation of ink libraries. This can co-exist with + # `enable_ink` above. + enable_pdf_ink2 = enable_pdf + + # Enable Ink Stubs. Only applicable when `enable_pdf_ink2` is true. + enable_pdf_ink2_stubs = true }
diff --git a/pdf/ink/BUILD.gn b/pdf/ink/BUILD.gn new file mode 100644 index 0000000..a422bd76 --- /dev/null +++ b/pdf/ink/BUILD.gn
@@ -0,0 +1,45 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//pdf/features.gni") + +assert(enable_pdf_ink2) + +group("ink") { + visibility = [ "//pdf/*" ] + + public_deps = [ ":interface" ] + + if (enable_pdf_ink2_stubs) { + deps = [ "//pdf/ink/stub" ] + } else { + # TODO(thestig): Add wrapper code. + deps = [ "//pdf/ink/wrapper" ] + } +} + +source_set("interface") { + visibility = [ "//pdf/*" ] + + sources = [ + "ink_brush.cc", + "ink_brush.h", + "ink_brush_behavior.h", + "ink_brush_family.cc", + "ink_brush_family.h", + "ink_brush_paint.cc", + "ink_brush_paint.h", + "ink_brush_tip.cc", + "ink_brush_tip.h", + "ink_in_progress_stroke.h", + "ink_skia_renderer.h", + "ink_stroke.h", + "ink_stroke_input.h", + "ink_stroke_input_batch.h", + ] + + configs += [ "//pdf:strict" ] + + public_deps = [ "//skia" ] +}
diff --git a/pdf/ink/DEPS b/pdf/ink/DEPS new file mode 100644 index 0000000..8346be4 --- /dev/null +++ b/pdf/ink/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + # This particular directory cannot depend on //base, as //base code conflicts + # with Ink code. + "-base", +]
diff --git a/pdf/ink/ink_brush.cc b/pdf/ink/ink_brush.cc new file mode 100644 index 0000000..90916a1 --- /dev/null +++ b/pdf/ink/ink_brush.cc
@@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush.h" + +namespace chrome_pdf { + +InkBrush::InkBrush() = default; + +InkBrush::~InkBrush() = default; + +} // namespace chrome_pdf
diff --git a/pdf/ink/ink_brush.h b/pdf/ink/ink_brush.h new file mode 100644 index 0000000..fdddb51 --- /dev/null +++ b/pdf/ink/ink_brush.h
@@ -0,0 +1,32 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_BRUSH_H_ +#define PDF_INK_INK_BRUSH_H_ + +#include <memory> + +#include "third_party/skia/include/core/SkColor.h" + +namespace chrome_pdf { + +class InkBrushFamily; + +class InkBrush { + public: + static std::unique_ptr<InkBrush> Create( + std::unique_ptr<InkBrushFamily> family, + SkColor color, + float size, + float epsilon); + + ~InkBrush(); + + protected: + InkBrush(); +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_BRUSH_H_
diff --git a/pdf/ink/ink_brush_behavior.h b/pdf/ink/ink_brush_behavior.h new file mode 100644 index 0000000..3ae537b --- /dev/null +++ b/pdf/ink/ink_brush_behavior.h
@@ -0,0 +1,48 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_BRUSH_BEHAVIOR_H_ +#define PDF_INK_INK_BRUSH_BEHAVIOR_H_ + +#include <optional> + +namespace chrome_pdf { + +struct InkBrushBehavior { + struct EnabledToolTypes { + bool operator==(const EnabledToolTypes& other) const; + bool operator!=(const EnabledToolTypes& other) const; + + bool unknown = false; + bool mouse = false; + bool touch = false; + bool stylus = false; + + bool HasAnyTypes() const; + bool HasAllTypes() const; + }; + + static constexpr EnabledToolTypes kAllToolTypes = {.unknown = true, + .mouse = true, + .touch = true, + .stylus = true}; + + enum OptionalInputProperty : int8_t { + kPressure, + kTilt, + kOrientation, + kTiltXAndY, + }; + + bool operator==(const InkBrushBehavior& other) const; + bool operator!=(const InkBrushBehavior& other) const; + + float response_time_seconds; + EnabledToolTypes enabled_tool_types = kAllToolTypes; + std::optional<OptionalInputProperty> is_fallback_for; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_BRUSH_BEHAVIOR_H_
diff --git a/pdf/ink/ink_brush_family.cc b/pdf/ink/ink_brush_family.cc new file mode 100644 index 0000000..378b0f4 --- /dev/null +++ b/pdf/ink/ink_brush_family.cc
@@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush_family.h" + +namespace chrome_pdf { + +InkBrushFamily::InkBrushFamily() = default; + +InkBrushFamily::~InkBrushFamily() = default; + +} // namespace chrome_pdf
diff --git a/pdf/ink/ink_brush_family.h b/pdf/ink/ink_brush_family.h new file mode 100644 index 0000000..5fb72a8b --- /dev/null +++ b/pdf/ink/ink_brush_family.h
@@ -0,0 +1,30 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_BRUSH_FAMILY_H_ +#define PDF_INK_INK_BRUSH_FAMILY_H_ + +#include <memory> +#include <string_view> + +namespace chrome_pdf { + +struct InkBrushPaint; +struct InkBrushTip; + +class InkBrushFamily { + public: + static std::unique_ptr<InkBrushFamily> Create(const InkBrushTip& tip, + const InkBrushPaint& paint, + std::string_view uri_string); + + ~InkBrushFamily(); + + protected: + InkBrushFamily(); +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_BRUSH_FAMILY_H_
diff --git a/pdf/ink/ink_brush_paint.cc b/pdf/ink/ink_brush_paint.cc new file mode 100644 index 0000000..dc56eec --- /dev/null +++ b/pdf/ink/ink_brush_paint.cc
@@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush_paint.h" + +namespace chrome_pdf { + +InkBrushPaint::InkBrushPaint() = default; + +InkBrushPaint::~InkBrushPaint() = default; + +InkBrushPaint::TextureLayer::TextureLayer() = default; + +InkBrushPaint::TextureLayer::TextureLayer(const InkBrushPaint::TextureLayer&) = + default; + +InkBrushPaint::TextureLayer& InkBrushPaint::TextureLayer::operator=( + const InkBrushPaint::TextureLayer&) = default; + +InkBrushPaint::TextureLayer::~TextureLayer() = default; + +} // namespace chrome_pdf
diff --git a/pdf/ink/ink_brush_paint.h b/pdf/ink/ink_brush_paint.h new file mode 100644 index 0000000..0ff039c --- /dev/null +++ b/pdf/ink/ink_brush_paint.h
@@ -0,0 +1,85 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_BRUSH_PAINT_H_ +#define PDF_INK_INK_BRUSH_PAINT_H_ + +#include <optional> +#include <string> +#include <vector> + +namespace chrome_pdf { + +struct InkBrushPaint { + InkBrushPaint(); + ~InkBrushPaint(); + + enum class TextureMapping { + kTiling, + kWinding, + }; + + enum class TextureSizeUnit { + kBrushSize, + kStrokeSize, + kStrokeCoordinates, + }; + + enum class BlendMode { + kModulate, + kDstIn, + kDstOut, + kSrcAtop, + kSrcIn, + kSrcOver, + }; + + struct TextureKeyframe { + float progress; + + std::optional<float> size_x; + std::optional<float> size_y; + std::optional<float> offset_x; + std::optional<float> offset_y; + std::optional<float> rotation_in_radians; + + std::optional<float> opacity; + }; + + struct TextureLayer { + TextureLayer(); + TextureLayer(const TextureLayer&); + TextureLayer& operator=(const TextureLayer&); + ~TextureLayer(); + + std::string color_texture_uri; + + TextureMapping mapping = TextureMapping::kTiling; + TextureSizeUnit size_unit = TextureSizeUnit::kStrokeCoordinates; + + float size_x = 1; + float size_y = 1; + float offset_x = 0; + float offset_y = 0; + float rotation_in_radians = 0; + + float size_jitter_x = 0; + float size_jitter_y = 0; + float offset_jitter_x = 0; + float offset_jitter_y = 0; + float rotation_jitter_in_radians = 0; + + float opacity = 1; + + std::vector<TextureKeyframe> keyframes; + + BlendMode blend_mode = BlendMode::kModulate; + }; + + std::vector<TextureLayer> texture_layers; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_BRUSH_PAINT_H_
diff --git a/pdf/ink/ink_brush_tip.cc b/pdf/ink/ink_brush_tip.cc new file mode 100644 index 0000000..142247b --- /dev/null +++ b/pdf/ink/ink_brush_tip.cc
@@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush_tip.h" + +namespace chrome_pdf { + +InkBrushTip::InkBrushTip() = default; + +InkBrushTip::~InkBrushTip() = default; + +} // namespace chrome_pdf
diff --git a/pdf/ink/ink_brush_tip.h b/pdf/ink/ink_brush_tip.h new file mode 100644 index 0000000..22e2109 --- /dev/null +++ b/pdf/ink/ink_brush_tip.h
@@ -0,0 +1,30 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_BRUSH_TIP_H_ +#define PDF_INK_INK_BRUSH_TIP_H_ + +#include <vector> + +#include "pdf/ink/ink_brush_behavior.h" + +namespace chrome_pdf { + +struct InkBrushTip { + InkBrushTip(); + ~InkBrushTip(); + + float scale_x = 1; + float scale_y = 1; + float corner_rounding = 1; + float slant = 0; + float pinch = 0; + float rotation = 0; + float opacity_multiplier = 1; + std::vector<InkBrushBehavior> behaviors; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_BRUSH_TIP_H_
diff --git a/pdf/ink/ink_in_progress_stroke.h b/pdf/ink/ink_in_progress_stroke.h new file mode 100644 index 0000000..77ae6ae --- /dev/null +++ b/pdf/ink/ink_in_progress_stroke.h
@@ -0,0 +1,41 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_IN_PROGRESS_STROKE_H_ +#define PDF_INK_INK_IN_PROGRESS_STROKE_H_ + +#include <memory> + +namespace chrome_pdf { + +class InkBrush; +class InkStroke; +class InkStrokeInputBatch; + +class InkInProgressStroke { + public: + static std::unique_ptr<InkInProgressStroke> Create(); + + InkInProgressStroke(const InkInProgressStroke&) = delete; + InkInProgressStroke& operator=(const InkInProgressStroke&) = delete; + virtual ~InkInProgressStroke() = default; + + virtual void Start(const InkBrush& brush) = 0; + + virtual bool EnqueueInputs(const InkStrokeInputBatch* real_inputs, + const InkStrokeInputBatch* predicted_inputs) = 0; + + virtual void FinishInputs() = 0; + + virtual bool UpdateShape(float current_elapsed_time_seconds) = 0; + + virtual std::unique_ptr<InkStroke> CopyToStroke() const = 0; + + protected: + InkInProgressStroke() = default; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_IN_PROGRESS_STROKE_H_
diff --git a/pdf/ink/ink_skia_renderer.h b/pdf/ink/ink_skia_renderer.h new file mode 100644 index 0000000..d5190694a --- /dev/null +++ b/pdf/ink/ink_skia_renderer.h
@@ -0,0 +1,58 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_SKIA_RENDERER_H_ +#define PDF_INK_INK_SKIA_RENDERER_H_ + +#include <memory> + +class GrDirectContext; +class SkCanvas; + +namespace chrome_pdf { + +class InkInProgressStroke; +class InkStroke; + +class InkSkiaRenderer { + public: + // NOTE: This is the equivalent to the following 3x3 matrix: + // + // a b c + // d e f + // 0 0 1 + // + // Thus the identity matrix is {1, 0, 0, 0, 1, 0}, and not {1, 0, 0, 1, 0, 0}. + struct AffineTransform { + float a; + float b; + float c; + float d; + float e; + float f; + }; + + static std::unique_ptr<InkSkiaRenderer> Create(); + + InkSkiaRenderer(const InkSkiaRenderer&) = delete; + InkSkiaRenderer& operator=(const InkSkiaRenderer&) = delete; + virtual ~InkSkiaRenderer() = default; + + // TODO(thestig): Remove `context` parameter. + virtual bool Draw(GrDirectContext* context, + const InkInProgressStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) = 0; + virtual bool Draw(GrDirectContext* context, + const InkStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) = 0; + + protected: + InkSkiaRenderer() = default; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_SKIA_RENDERER_H_
diff --git a/pdf/ink/ink_stroke.h b/pdf/ink/ink_stroke.h new file mode 100644 index 0000000..d386871 --- /dev/null +++ b/pdf/ink/ink_stroke.h
@@ -0,0 +1,20 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_STROKE_H_ +#define PDF_INK_INK_STROKE_H_ + +namespace chrome_pdf { + +class InkStroke { + public: + ~InkStroke() = default; + + protected: + InkStroke() = default; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_STROKE_H_
diff --git a/pdf/ink/ink_stroke_input.h b/pdf/ink/ink_stroke_input.h new file mode 100644 index 0000000..7d940c06 --- /dev/null +++ b/pdf/ink/ink_stroke_input.h
@@ -0,0 +1,28 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_STROKE_INPUT_H_ +#define PDF_INK_INK_STROKE_INPUT_H_ + +namespace chrome_pdf { + +struct InkStrokeInput { + enum class ToolType : int8_t { kUnknown, kMouse, kTouch, kStylus }; + + static constexpr float kNoPressure = -1; + static constexpr float kNoTilt = -1; + static constexpr float kNoOrientation = -1; + + ToolType tool_type = ToolType::kUnknown; + float position_x; + float position_y; + float elapsed_time_seconds; + float pressure = kNoPressure; + float tilt_in_radians = kNoTilt; + float orientation_in_radians = kNoOrientation; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_STROKE_INPUT_H_
diff --git a/pdf/ink/ink_stroke_input_batch.h b/pdf/ink/ink_stroke_input_batch.h new file mode 100644 index 0000000..b4c1898 --- /dev/null +++ b/pdf/ink/ink_stroke_input_batch.h
@@ -0,0 +1,28 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_INK_STROKE_INPUT_BATCH_H_ +#define PDF_INK_INK_STROKE_INPUT_BATCH_H_ + +#include <memory> +#include <vector> + +#include "pdf/ink/ink_stroke_input.h" + +namespace chrome_pdf { + +class InkStrokeInputBatch { + public: + static std::unique_ptr<InkStrokeInputBatch> Create( + const std::vector<InkStrokeInput>& inputs); + + ~InkStrokeInputBatch() = default; + + protected: + InkStrokeInputBatch() = default; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_INK_STROKE_INPUT_BATCH_H_
diff --git a/pdf/ink/stub/BUILD.gn b/pdf/ink/stub/BUILD.gn new file mode 100644 index 0000000..2892974d --- /dev/null +++ b/pdf/ink/stub/BUILD.gn
@@ -0,0 +1,30 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//pdf/features.gni") + +assert(enable_pdf_ink2) + +source_set("stub") { + visibility = [ "//pdf/ink" ] + + sources = [ + "ink_brush_family_stub.cc", + "ink_brush_stub.cc", + "ink_in_progress_stroke_stub.cc", + "ink_in_progress_stroke_stub.h", + "ink_skia_renderer_stub.cc", + "ink_skia_renderer_stub.h", + "ink_stroke_input_batch_stub.cc", + ] + + configs += [ "//pdf:strict" ] + + public_deps = [ "//pdf/ink:interface" ] + + deps = [ + "//base", + "//skia", + ] +}
diff --git a/pdf/ink/stub/DEPS b/pdf/ink/stub/DEPS new file mode 100644 index 0000000..bb28a61 --- /dev/null +++ b/pdf/ink/stub/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + # This overrides the -base rule in the parent directory, as this is a stub and + # there is no Ink code here. + "+base", +]
diff --git a/pdf/ink/stub/ink_brush_family_stub.cc b/pdf/ink/stub/ink_brush_family_stub.cc new file mode 100644 index 0000000..5574740 --- /dev/null +++ b/pdf/ink/stub/ink_brush_family_stub.cc
@@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush_family.h" + +#include <memory> + +#include "base/memory/ptr_util.h" + +namespace chrome_pdf { + +// static +std::unique_ptr<InkBrushFamily> InkBrushFamily::Create( + const InkBrushTip& tip, + const InkBrushPaint& paint, + std::string_view uri_string) { + // Protected ctor. + return base::WrapUnique(new InkBrushFamily()); +} + +} // namespace chrome_pdf
diff --git a/pdf/ink/stub/ink_brush_stub.cc b/pdf/ink/stub/ink_brush_stub.cc new file mode 100644 index 0000000..1218e7fe --- /dev/null +++ b/pdf/ink/stub/ink_brush_stub.cc
@@ -0,0 +1,29 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_brush.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "pdf/ink/ink_brush_family.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace chrome_pdf { + +// static +std::unique_ptr<InkBrush> InkBrush::Create( + std::unique_ptr<InkBrushFamily> family, + SkColor color, + float size, + float epsilon) { + if (!family) { + return nullptr; + } + + // Protected ctor. + return base::WrapUnique(new InkBrush()); +} + +} // namespace chrome_pdf
diff --git a/pdf/ink/stub/ink_in_progress_stroke_stub.cc b/pdf/ink/stub/ink_in_progress_stroke_stub.cc new file mode 100644 index 0000000..7e0a89b --- /dev/null +++ b/pdf/ink/stub/ink_in_progress_stroke_stub.cc
@@ -0,0 +1,36 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/stub/ink_in_progress_stroke_stub.h" + +#include <memory> + +namespace chrome_pdf { + +// static +std::unique_ptr<InkInProgressStroke> InkInProgressStroke::Create() { + return nullptr; +} + +InkInProgressStrokeStub::~InkInProgressStrokeStub() = default; + +void InkInProgressStrokeStub::Start(const InkBrush& brush) {} + +bool InkInProgressStrokeStub::EnqueueInputs( + const InkStrokeInputBatch* real_inputs, + const InkStrokeInputBatch* predicted_inputs) { + return false; +} + +void InkInProgressStrokeStub::FinishInputs() {} + +bool InkInProgressStrokeStub::UpdateShape(float current_elapsed_time_seconds) { + return false; +} + +std::unique_ptr<InkStroke> InkInProgressStrokeStub::CopyToStroke() const { + return nullptr; +} + +} // namespace chrome_pdf
diff --git a/pdf/ink/stub/ink_in_progress_stroke_stub.h b/pdf/ink/stub/ink_in_progress_stroke_stub.h new file mode 100644 index 0000000..0c0ce8e3 --- /dev/null +++ b/pdf/ink/stub/ink_in_progress_stroke_stub.h
@@ -0,0 +1,27 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_STUB_INK_IN_PROGRESS_STROKE_STUB_H_ +#define PDF_INK_STUB_INK_IN_PROGRESS_STROKE_STUB_H_ + +#include "pdf/ink/ink_in_progress_stroke.h" + +namespace chrome_pdf { + +class InkInProgressStrokeStub : public InkInProgressStroke { + public: + ~InkInProgressStrokeStub() override; + + // InkInProgressStroke: + void Start(const InkBrush& brush) override; + bool EnqueueInputs(const InkStrokeInputBatch* real_inputs, + const InkStrokeInputBatch* predicted_inputs) override; + void FinishInputs() override; + bool UpdateShape(float current_elapsed_time_seconds) override; + std::unique_ptr<InkStroke> CopyToStroke() const override; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_STUB_INK_IN_PROGRESS_STROKE_STUB_H_
diff --git a/pdf/ink/stub/ink_skia_renderer_stub.cc b/pdf/ink/stub/ink_skia_renderer_stub.cc new file mode 100644 index 0000000..d77ed11 --- /dev/null +++ b/pdf/ink/stub/ink_skia_renderer_stub.cc
@@ -0,0 +1,30 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/stub/ink_skia_renderer_stub.h" + +#include <memory> + +namespace chrome_pdf { + +// static +std::unique_ptr<InkSkiaRenderer> InkSkiaRenderer::Create() { + return nullptr; +} + +bool InkSkiaRendererStub::Draw(GrDirectContext* context, + const InkInProgressStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) { + return false; +} + +bool InkSkiaRendererStub::Draw(GrDirectContext* context, + const InkStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) { + return false; +} + +} // namespace chrome_pdf
diff --git a/pdf/ink/stub/ink_skia_renderer_stub.h b/pdf/ink/stub/ink_skia_renderer_stub.h new file mode 100644 index 0000000..e96f3c9 --- /dev/null +++ b/pdf/ink/stub/ink_skia_renderer_stub.h
@@ -0,0 +1,26 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_INK_STUB_INK_SKIA_RENDERER_STUB_H_ +#define PDF_INK_STUB_INK_SKIA_RENDERER_STUB_H_ + +#include "pdf/ink/ink_skia_renderer.h" + +namespace chrome_pdf { + +class InkSkiaRendererStub : public InkSkiaRenderer { + public: + bool Draw(GrDirectContext* context, + const InkInProgressStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) override; + bool Draw(GrDirectContext* context, + const InkStroke& stroke, + const AffineTransform& object_to_canvas, + SkCanvas& canvas) override; +}; + +} // namespace chrome_pdf + +#endif // PDF_INK_STUB_INK_SKIA_RENDERER_STUB_H_
diff --git a/pdf/ink/stub/ink_stroke_input_batch_stub.cc b/pdf/ink/stub/ink_stroke_input_batch_stub.cc new file mode 100644 index 0000000..15fcd87e --- /dev/null +++ b/pdf/ink/stub/ink_stroke_input_batch_stub.cc
@@ -0,0 +1,17 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/ink/ink_stroke_input_batch.h" + +#include <memory> + +namespace chrome_pdf { + +// static +std::unique_ptr<InkStrokeInputBatch> InkStrokeInputBatch::Create( + const std::vector<InkStrokeInput>& inputs) { + return nullptr; +} + +} // namespace chrome_pdf
diff --git a/pdf/metrics_handler.cc b/pdf/metrics_handler.cc index b5846a9..1ead538 100644 --- a/pdf/metrics_handler.cc +++ b/pdf/metrics_handler.cc
@@ -37,4 +37,8 @@ base::UmaHistogramEnumeration("PDF.FormType", metadata.form_type); } +void MetricsHandler::RecordAccessibilityIsDocTagged(bool is_tagged) { + base::UmaHistogramBoolean("Accessibility.PDF.IsPDFTagged", is_tagged); +} + } // namespace chrome_pdf
diff --git a/pdf/metrics_handler.h b/pdf/metrics_handler.h index ce765130..634096af 100644 --- a/pdf/metrics_handler.h +++ b/pdf/metrics_handler.h
@@ -18,6 +18,7 @@ ~MetricsHandler(); void RecordDocumentMetrics(const DocumentMetadata& metadata); + void RecordAccessibilityIsDocTagged(bool is_tagged); }; } // namespace chrome_pdf
diff --git a/pdf/pdf.cc b/pdf/pdf.cc index e7e69e13..d635036 100644 --- a/pdf/pdf.cc +++ b/pdf/pdf.cc
@@ -15,9 +15,16 @@ #include "pdf/pdf_engine.h" #include "pdf/pdf_features.h" #include "pdf/pdf_init.h" +#include "services/screen_ai/buildflags/buildflags.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_f.h" +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +#include "base/functional/callback_forward.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + namespace chrome_pdf { namespace { @@ -173,4 +180,15 @@ input_buffer, pages_per_sheet, page_size, printable_area); } +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +std::vector<uint8_t> Searchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback) { + ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/false); + PDFEngineExports* engine_exports = PDFEngineExports::Get(); + return engine_exports->Searchify(pdf_buffer, std::move(perform_ocr_callback)); +} +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + } // namespace chrome_pdf
diff --git a/pdf/pdf.h b/pdf/pdf.h index 998d0e7..eebc6bf 100644 --- a/pdf/pdf.h +++ b/pdf/pdf.h
@@ -12,6 +12,7 @@ #include "base/values.h" #include "build/build_config.h" #include "pdf/document_metadata.h" +#include "services/screen_ai/buildflags/buildflags.h" #if BUILDFLAG(IS_CHROMEOS) #include "pdf/flatten_pdf_result.h" @@ -21,6 +22,12 @@ #include <windows.h> #endif +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +#include "base/functional/callback_forward.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + namespace gfx { class Rect; class Size; @@ -212,6 +219,25 @@ const gfx::Size& page_size, const gfx::Rect& printable_area); +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +// Converts an inaccessible PDF to a searchable PDF. +// `pdf_buffer` is the buffer of the inaccessible PDF. +// `searchified_callback` is the callback that is called with the searchified +// PDF when the conversion is done. +// `perform_ocr_callback` is the callback that takes an image and outputs +// the OCR result. It may be called multiple times. +// +// The conversion is done by performing OCR on each image in the PDF and adding +// a layer of invisible text to the PDF to make text on images accessible. Each +// execution should take place in an isolated process, and each process should +// be terminated upon completion of the conversion. An empty vector is returned +// on failure. +std::vector<uint8_t> Searchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback); +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + } // namespace chrome_pdf #endif // PDF_PDF_H_
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 93f8d82..a548ad2 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -19,6 +19,7 @@ #include "build/build_config.h" #include "pdf/document_layout.h" #include "printing/mojom/print.mojom-forward.h" +#include "services/screen_ai/buildflags/buildflags.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" #include "ui/base/window_open_disposition.h" @@ -35,6 +36,10 @@ #include "pdf/flatten_pdf_result.h" #endif +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +#include "services/screen_ai/public/mojom/screen_ai_service.mojom-forward.h" +#endif + class SkBitmap; namespace blink { @@ -473,6 +478,8 @@ // Returns the focus info of current focus item. virtual AccessibilityFocusInfo GetFocusInfo() = 0; + virtual bool IsPDFDocTagged() = 0; + virtual uint32_t GetLoadedByteSize() = 0; virtual bool ReadLoadedBytes(uint32_t length, void* buffer) = 0; @@ -580,6 +587,15 @@ virtual std::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, int page_index) = 0; + +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + // Converts an inaccessible PDF to a searchable PDF. See `Searchify` in pdf.h + // for more details. + virtual std::vector<uint8_t> Searchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback) = 0; +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) }; } // namespace chrome_pdf
diff --git a/pdf/pdf_features.cc b/pdf/pdf_features.cc index 0ec88a3d..b57be8c8 100644 --- a/pdf/pdf_features.cc +++ b/pdf/pdf_features.cc
@@ -4,8 +4,10 @@ #include "pdf/pdf_features.h" -namespace chrome_pdf { -namespace features { +#include "base/feature_list.h" +#include "pdf/buildflags.h" + +namespace chrome_pdf::features { BASE_FEATURE(kAccessiblePDFForm, "AccessiblePDFForm", @@ -36,5 +38,8 @@ "PdfXfaSupport", base::FEATURE_DISABLED_BY_DEFAULT); -} // namespace features -} // namespace chrome_pdf +#if BUILDFLAG(ENABLE_PDF_INK2) +BASE_FEATURE(kPdfInk2, "PdfInk2", base::FEATURE_DISABLED_BY_DEFAULT); +#endif + +} // namespace chrome_pdf::features
diff --git a/pdf/pdf_features.h b/pdf/pdf_features.h index 3ba036b..10e20a8 100644 --- a/pdf/pdf_features.h +++ b/pdf/pdf_features.h
@@ -9,9 +9,11 @@ #define PDF_PDF_FEATURES_H_ #include "base/feature_list.h" +#include "pdf/buildflags.h" -namespace chrome_pdf { -namespace features { +static_assert(BUILDFLAG(ENABLE_PDF), "ENABLE_PDF not set to true"); + +namespace chrome_pdf::features { BASE_DECLARE_FEATURE(kAccessiblePDFForm); BASE_DECLARE_FEATURE(kPdfIncrementalLoading); @@ -21,7 +23,10 @@ BASE_DECLARE_FEATURE(kPdfUseSkiaRenderer); BASE_DECLARE_FEATURE(kPdfXfaSupport); -} // namespace features -} // namespace chrome_pdf +#if BUILDFLAG(ENABLE_PDF_INK2) +BASE_DECLARE_FEATURE(kPdfInk2); +#endif + +} // namespace chrome_pdf::features #endif // PDF_PDF_FEATURES_H_
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc index 7b065d7..9b4d5d6 100644 --- a/pdf/pdf_view_web_plugin.cc +++ b/pdf/pdf_view_web_plugin.cc
@@ -2431,6 +2431,9 @@ pdf_accessibility_data_handler_->SetAccessibilityDocInfo( GetAccessibilityDocInfo()); + // Record whether the PDF is tagged when opened by an accessibility user. + metrics_handler_->RecordAccessibilityIsDocTagged(engine_->IsPDFDocTagged()); + // If the document contents isn't accessible, don't send anything more. if (!(engine_->HasPermission(DocumentPermission::kCopy) || engine_->HasPermission(DocumentPermission::kCopyAccessible))) {
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index dfc7065..2678f15 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -63,6 +63,7 @@ #include "third_party/pdfium/public/cpp/fpdf_scopers.h" #include "third_party/pdfium/public/fpdf_annot.h" #include "third_party/pdfium/public/fpdf_attachment.h" +#include "third_party/pdfium/public/fpdf_catalog.h" #include "third_party/pdfium/public/fpdf_ext.h" #include "third_party/pdfium/public/fpdf_fwlevent.h" #include "third_party/pdfium/public/fpdf_ppo.h" @@ -1126,6 +1127,10 @@ return focus_info; } +bool PDFiumEngine::IsPDFDocTagged() { + return FPDFCatalog_IsTagged(doc()); +} + uint32_t PDFiumEngine::GetLoadedByteSize() { return doc_loader_->GetDocumentSize(); }
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index d214069..c33e41f 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -186,6 +186,7 @@ void KillFormFocus() override; void UpdateFocus(bool has_focus) override; AccessibilityFocusInfo GetFocusInfo() override; + bool IsPDFDocTagged() override; uint32_t GetLoadedByteSize() override; bool ReadLoadedBytes(uint32_t length, void* buffer) override; void RequestThumbnail(int page_index,
diff --git a/pdf/pdfium/pdfium_engine_exports.cc b/pdf/pdfium/pdfium_engine_exports.cc index d3c55a1..1c6024f 100644 --- a/pdf/pdfium/pdfium_engine_exports.cc +++ b/pdf/pdfium/pdfium_engine_exports.cc
@@ -23,6 +23,7 @@ #include "pdf/pdfium/pdfium_unsupported_features.h" #include "printing/nup_parameters.h" #include "printing/units.h" +#include "services/screen_ai/buildflags/buildflags.h" #include "third_party/pdfium/public/cpp/fpdf_scopers.h" #include "third_party/pdfium/public/fpdf_attachment.h" #include "third_party/pdfium/public/fpdf_catalog.h" @@ -35,6 +36,13 @@ #include "ui/gfx/geometry/size_f.h" #include "ui/gfx/geometry/vector2d.h" +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +#include "base/functional/callback.h" +#include "pdf/pdfium/pdfium_searchify.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" +#endif + using printing::ConvertUnitFloat; using printing::kPointsPerInch; @@ -554,4 +562,13 @@ return gfx::SizeF(size.width, size.height); } +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +std::vector<uint8_t> PDFiumEngineExports::Searchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback) { + return PDFiumSearchify(pdf_buffer, std::move(perform_ocr_callback)); +} +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h index 85d1da3e..82d84299 100644 --- a/pdf/pdfium/pdfium_engine_exports.h +++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -11,6 +11,13 @@ #include "build/build_config.h" #include "pdf/document_metadata.h" #include "pdf/pdf_engine.h" +#include "services/screen_ai/buildflags/buildflags.h" + +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) +#include "base/functional/callback_forward.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "third_party/skia/include/core/SkBitmap.h" +#endif namespace chrome_pdf { @@ -61,6 +68,12 @@ std::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, int page_index) override; +#if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + std::vector<uint8_t> Searchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback) override; +#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc index af290c23..042fe15 100644 --- a/pdf/pdfium/pdfium_engine_exports_unittest.cc +++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -3,11 +3,18 @@ // found in the LICENSE file. #include <optional> +#include <utility> #include "base/files/file_util.h" +#include "base/functional/bind.h" +#include "base/functional/callback.h" #include "base/path_service.h" +#include "base/test/mock_callback.h" #include "pdf/pdf.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" @@ -145,4 +152,36 @@ } } +TEST_F(PDFiumEngineExportsTest, Searchify) { + base::FilePath pdf_path = + pdf_data_dir().Append(FILE_PATH_LITERAL("image_alt_text.pdf")); + std::optional<std::vector<uint8_t>> pdf_buffer = + base::ReadFileToBytes(pdf_path); + ASSERT_TRUE(pdf_buffer.has_value()); + + base::MockCallback<base::RepeatingCallback< + screen_ai::mojom::VisualAnnotationPtr(const SkBitmap&)>> + perform_ocr_callback; + EXPECT_CALL(perform_ocr_callback, Run) + .Times(3) + .WillRepeatedly([](const SkBitmap& bitmap) { + auto annotation = screen_ai::mojom::VisualAnnotation::New(); + auto line_box = screen_ai::mojom::LineBox::New(); + line_box->baseline_box = gfx::Rect(0, 0, 100, 100); + line_box->baseline_box_angle = 0; + line_box->bounding_box = gfx::Rect(0, 0, 100, 100); + line_box->bounding_box_angle = 0; + auto word_box = screen_ai::mojom::WordBox::New(); + word_box->word = "foo"; + word_box->bounding_box = gfx::Rect(0, 0, 100, 100); + word_box->bounding_box_angle = 0; + line_box->words.push_back(std::move(word_box)); + annotation->lines.push_back(std::move(line_box)); + return annotation; + }); + std::vector<uint8_t> output_pdf_buffer = + Searchify(*pdf_buffer, perform_ocr_callback.Get()); + ASSERT_GT(output_pdf_buffer.size(), 0U); +} + } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_ocr.cc b/pdf/pdfium/pdfium_ocr.cc new file mode 100644 index 0000000..9628672b --- /dev/null +++ b/pdf/pdfium/pdfium_ocr.cc
@@ -0,0 +1,85 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/pdfium/pdfium_ocr.h" + +#include <stddef.h> + +#include "base/check.h" +#include "base/check_op.h" +#include "base/logging.h" +#include "third_party/pdfium/public/cpp/fpdf_scopers.h" +#include "third_party/pdfium/public/fpdf_edit.h" +#include "third_party/pdfium/public/fpdfview.h" +#include "third_party/skia/include/core/SkAlphaType.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColorType.h" +#include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/core/SkPixmap.h" + +namespace chrome_pdf { + +SkBitmap GetImageForOcr(FPDF_DOCUMENT doc, + FPDF_PAGE page, + int page_object_index) { + SkBitmap bitmap; + + FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, page_object_index); + if (FPDFPageObj_GetType(page_object) != FPDF_PAGEOBJ_IMAGE) { + return bitmap; + } + + // OCR needs the image with the highest available quality. To get it, the + // image transform matrix is reset to no-scale, the bitmap is extracted, + // and then the original matrix is restored. + FS_MATRIX original_matrix; + if (!FPDFPageObj_GetMatrix(page_object, &original_matrix)) { + DLOG(ERROR) << "Failed to get original matrix"; + return bitmap; + } + + // Get the actual image size. + unsigned int width; + unsigned int height; + if (!FPDFImageObj_GetImagePixelSize(page_object, &width, &height)) { + DLOG(ERROR) << "Failed to get image size"; + return bitmap; + } + + // Resize the matrix to actual size. + FS_MATRIX new_matrix = {static_cast<float>(width), 0, 0, + static_cast<float>(height), 0, 0}; + if (!FPDFPageObj_SetMatrix(page_object, &new_matrix)) { + DLOG(ERROR) << "Failed to set new matrix on image"; + return bitmap; + } + + ScopedFPDFBitmap raw_bitmap( + FPDFImageObj_GetRenderedBitmap(doc, page, page_object)); + + if (!raw_bitmap) { + DLOG(ERROR) << "Failed to get rendered bitmap"; + return bitmap; + } + + // Restore the original matrix. + CHECK(FPDFPageObj_SetMatrix(page_object, &original_matrix)); + + CHECK_EQ(FPDFBitmap_GetFormat(raw_bitmap.get()), FPDFBitmap_BGRA); + SkImageInfo info = + SkImageInfo::Make(FPDFBitmap_GetWidth(raw_bitmap.get()), + FPDFBitmap_GetHeight(raw_bitmap.get()), + kBGRA_8888_SkColorType, kOpaque_SkAlphaType); + const size_t row_bytes = FPDFBitmap_GetStride(raw_bitmap.get()); + SkPixmap pixels(info, FPDFBitmap_GetBuffer(raw_bitmap.get()), row_bytes); + if (!bitmap.tryAllocPixels(info, row_bytes)) { + DLOG(ERROR) << "Failed to allocate pixel memory"; + return bitmap; + } + bitmap.writePixels(pixels); + + return bitmap; +} + +} // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_ocr.h b/pdf/pdfium/pdfium_ocr.h new file mode 100644 index 0000000..663f764 --- /dev/null +++ b/pdf/pdfium/pdfium_ocr.h
@@ -0,0 +1,19 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_PDFIUM_PDFIUM_OCR_H_ +#define PDF_PDFIUM_PDFIUM_OCR_H_ + +#include "third_party/pdfium/public/fpdfview.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace chrome_pdf { + +SkBitmap GetImageForOcr(FPDF_DOCUMENT doc, + FPDF_PAGE page, + int page_object_index); + +} // namespace chrome_pdf + +#endif // PDF_PDFIUM_PDFIUM_OCR_H_
diff --git a/pdf/pdfium/pdfium_page.cc b/pdf/pdfium/pdfium_page.cc index e1211a51..c0d0945 100644 --- a/pdf/pdfium/pdfium_page.cc +++ b/pdf/pdfium/pdfium_page.cc
@@ -24,6 +24,7 @@ #include "pdf/accessibility_structs.h" #include "pdf/pdfium/pdfium_api_string_buffer_adapter.h" #include "pdf/pdfium/pdfium_engine.h" +#include "pdf/pdfium/pdfium_ocr.h" #include "pdf/pdfium/pdfium_unsupported_features.h" #include "pdf/ui/thumbnail.h" #include "printing/units.h" @@ -32,8 +33,7 @@ #include "third_party/pdfium/public/fpdf_catalog.h" #include "third_party/pdfium/public/fpdf_edit.h" #include "third_party/pdfium/public/fpdfview.h" -#include "third_party/skia/include/core/SkImageInfo.h" -#include "third_party/skia/include/core/SkPixmap.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/accessibility/accessibility_features.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_f.h" @@ -778,58 +778,9 @@ } SkBitmap PDFiumPage::GetImageForOcr(int page_object_index) { - SkBitmap bitmap; - FPDF_PAGE page = GetPage(); - FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, page_object_index); - - if (FPDFPageObj_GetType(page_object) != FPDF_PAGEOBJ_IMAGE) { - return bitmap; - } - - // OCR needs the image with the highest available quality. To get it, the - // image transform matrix is reset to no-scale, the bitmap is extracted, - // and then the original matrix is restored. - FS_MATRIX original_matrix; - if (!FPDFPageObj_GetMatrix(page_object, &original_matrix)) { - return bitmap; - } - - // Get the actual image size. - unsigned int width; - unsigned int height; - if (!FPDFImageObj_GetImagePixelSize(page_object, &width, &height)) { - return bitmap; - } - - // Resize the matrix to actual size. - FS_MATRIX new_matrix = {static_cast<float>(width), 0, 0, - static_cast<float>(height), 0, 0}; - if (!FPDFPageObj_SetMatrix(page_object, &new_matrix)) { - return bitmap; - } - - ScopedFPDFBitmap raw_bitmap( - FPDFImageObj_GetRenderedBitmap(engine_->doc(), page, page_object)); - - // Restore the original matrix. - CHECK(FPDFPageObj_SetMatrix(page_object, &original_matrix)); - - if (!raw_bitmap) { - return SkBitmap(); - } - - CHECK_EQ(FPDFBitmap_GetFormat(raw_bitmap.get()), FPDFBitmap_BGRA); - SkImageInfo info = - SkImageInfo::Make(FPDFBitmap_GetWidth(raw_bitmap.get()), - FPDFBitmap_GetHeight(raw_bitmap.get()), - kBGRA_8888_SkColorType, kOpaque_SkAlphaType); - const size_t row_bytes = FPDFBitmap_GetStride(raw_bitmap.get()); - SkPixmap pixels(info, FPDFBitmap_GetBuffer(raw_bitmap.get()), row_bytes); - if (!bitmap.tryAllocPixels(info, row_bytes)) { - return bitmap; - } - bitmap.writePixels(pixels); + SkBitmap bitmap = + ::chrome_pdf::GetImageForOcr(engine_->doc(), page, page_object_index); SkBitmapOperations::RotationAmount rotation; switch (FPDFPage_GetRotation(page)) { @@ -846,6 +797,11 @@ break; } + // TODO(crbug/40068467): Currently, `::chrome_pdf::GetImageForOcr` returns the + // full image stored in the PDF without applying the transformation matrix. To + // ensure the image sent to OCR matches how users view it on the browser, + // rotate the bitmap by the page's rotation. We may also need to consider the + // transformation of the image. return SkBitmapOperations::Rotate(bitmap, rotation); }
diff --git a/pdf/pdfium/pdfium_page.h b/pdf/pdfium/pdfium_page.h index 6b1c522d..63c8478 100644 --- a/pdf/pdfium/pdfium_page.h +++ b/pdf/pdfium/pdfium_page.h
@@ -21,6 +21,7 @@ #include "third_party/pdfium/public/fpdf_doc.h" #include "third_party/pdfium/public/fpdf_formfill.h" #include "third_party/pdfium/public/fpdf_text.h" +#include "third_party/pdfium/public/fpdfview.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h"
diff --git a/pdf/pdfium/pdfium_searchify.cc b/pdf/pdfium/pdfium_searchify.cc new file mode 100644 index 0000000..49b5b035 --- /dev/null +++ b/pdf/pdfium/pdfium_searchify.cc
@@ -0,0 +1,259 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/pdfium/pdfium_searchify.h" + +#include <algorithm> +#include <numbers> +#include <vector> + +#include "base/check.h" +#include "base/check_op.h" +#include "base/functional/callback.h" +#include "base/strings/utf_string_conversions.h" +#include "pdf/pdfium/pdfium_mem_buffer_file_write.h" +#include "pdf/pdfium/pdfium_ocr.h" +#include "pdf/pdfium/pdfium_searchify_font.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom.h" +#include "third_party/pdfium/public/cpp/fpdf_scopers.h" +#include "third_party/pdfium/public/fpdf_edit.h" +#include "third_party/pdfium/public/fpdf_save.h" +#include "third_party/pdfium/public/fpdfview.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkImageInfo.h" +#include "third_party/skia/include/core/SkPixmap.h" + +namespace chrome_pdf { + +namespace { + +std::vector<uint32_t> Utf8ToCharcodes(const std::string& string) { + std::u16string utf16_str = base::UTF8ToUTF16(string); + std::vector<uint32_t> charcodes; + charcodes.reserve(utf16_str.size()); + for (auto c : utf16_str) { + charcodes.push_back(c); + } + return charcodes; +} + +struct BoundingBoxOrigin { + double x; + double y; + double theta; +}; + +// The coordinate systems between OCR and PDF are different. OCR's origin is at +// top-left, so we need to convert them to PDF's bottom-left. +BoundingBoxOrigin ConvertToPdfOrigin(int x, + int y, + int width, + int height, + double angle, + double coordinate_system_height) { + double theta = angle * std::numbers::pi / 180; + return {.x = x - (sin(theta) * height), + .y = coordinate_system_height - (y + cos(theta) * height), + .theta = -theta}; +} + +// Project the text object's origin to the baseline's origin. +BoundingBoxOrigin ProjectToBaseline(const BoundingBoxOrigin& origin, + const BoundingBoxOrigin& baseline_origin) { + // The length between `origin` and `baseline_origin`. + double length = (origin.x - baseline_origin.x) * cos(baseline_origin.theta) + + (origin.y - baseline_origin.y) * sin(baseline_origin.theta); + return {.x = baseline_origin.x + length * cos(baseline_origin.theta), + .y = baseline_origin.y + length * sin(baseline_origin.theta), + .theta = baseline_origin.theta}; +} + +void AddTextOnImage(FPDF_DOCUMENT document, + FPDF_PAGE page, + FPDF_FONT font, + FPDF_PAGEOBJECT image, + screen_ai::mojom::VisualAnnotationPtr annotation) { + FS_QUADPOINTSF quadpoints; + if (!FPDFPageObj_GetRotatedBounds(image, &quadpoints)) { + DLOG(ERROR) << "Failed to get image rendered dimensions"; + return; + } + double image_rendered_width = sqrt(pow(quadpoints.x1 - quadpoints.x2, 2) + + pow(quadpoints.y1 - quadpoints.y2, 2)); + double image_rendered_height = sqrt(pow(quadpoints.x2 - quadpoints.x3, 2) + + pow(quadpoints.y2 - quadpoints.y3, 2)); + unsigned int image_pixel_width; + unsigned int image_pixel_height; + if (!FPDFImageObj_GetImagePixelSize(image, &image_pixel_width, + &image_pixel_height)) { + DLOG(ERROR) << "Failed to get image dimensions"; + return; + } + FS_MATRIX image_matrix; + if (!FPDFPageObj_GetMatrix(image, &image_matrix)) { + DLOG(ERROR) << "Failed to get image matrix"; + return; + } + + for (const auto& line : annotation->lines) { + BoundingBoxOrigin baseline_origin = ConvertToPdfOrigin( + line->baseline_box.x(), line->baseline_box.y(), + line->baseline_box.width(), line->baseline_box.height(), + line->baseline_box_angle, image_rendered_height); + + for (const auto& word : line->words) { + double width = word->bounding_box.width(); + double height = word->bounding_box.height(); + + if (width == 0 || height == 0) { + continue; + } + + ScopedFPDFPageObject text( + FPDFPageObj_CreateTextObj(document, font, height)); + CHECK(text); + + std::string word_string = word->word; + // TODO(crbug.com/41487613): A more accurate width would be the distance + // from current word's origin to next word's origin. + if (word->has_space_after) { + word_string.push_back(' '); + } + + if (word_string.empty()) { + DLOG(ERROR) << "Got empty word"; + continue; + } + + std::vector<uint32_t> charcodes = Utf8ToCharcodes(word_string); + if (!FPDFText_SetCharcodes(text.get(), charcodes.data(), + charcodes.size())) { + DLOG(ERROR) << "Failed to set charcodes"; + continue; + } + + // Make text invisible + if (!FPDFTextObj_SetTextRenderMode(text.get(), + FPDF_TEXTRENDERMODE_INVISIBLE)) { + DLOG(ERROR) << "Failed to make text invisible"; + continue; + } + + float left; + float bottom; + float right; + float top; + if (!FPDFPageObj_GetBounds(text.get(), &left, &bottom, &right, &top)) { + DLOG(ERROR) << "Failed to get the bounding box of original text object"; + continue; + } + double original_text_object_width = right - left; + double original_text_object_height = top - bottom; + CHECK_GT(original_text_object_width, 0); + CHECK_GT(original_text_object_height, 0); + double width_scale = width / original_text_object_width; + double height_scale = height / original_text_object_height; + FPDFPageObj_Transform(text.get(), width_scale, 0, 0, height_scale, 0, 0); + + // Move text object to the corresponding text position on the full image. + BoundingBoxOrigin origin = ConvertToPdfOrigin( + word->bounding_box.x(), word->bounding_box.y(), width, height, + word->bounding_box_angle, image_rendered_height); + origin = ProjectToBaseline(origin, baseline_origin); + double a = cos(origin.theta); + double b = sin(origin.theta); + double c = -sin(origin.theta); + double d = cos(origin.theta); + double e = origin.x; + double f = origin.y; + if (word->direction == + screen_ai::mojom::Direction::DIRECTION_RIGHT_TO_LEFT) { + a = -a; + b = -b; + e += cos(origin.theta) * width; + f += sin(origin.theta) * width; + } + FPDFPageObj_Transform(text.get(), a, b, c, d, e, f); + + // Scale from full image size to rendered image size on the PDF. + FPDFPageObj_Transform(text.get(), + image_rendered_width / image_pixel_width, 0, 0, + image_rendered_height / image_pixel_height, 0, 0); + + // Apply the image's transformation matrix on the PDF page without the + // scaling matrix. + FPDFPageObj_Transform(text.get(), image_matrix.a / image_rendered_width, + image_matrix.b / image_rendered_width, + image_matrix.c / image_rendered_height, + image_matrix.d / image_rendered_height, + image_matrix.e, image_matrix.f); + + FPDFPage_InsertObject(page, text.release()); + } + } +} + +} // namespace + +std::vector<uint8_t> PDFiumSearchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback) { + ScopedFPDFDocument document( + FPDF_LoadMemDocument64(pdf_buffer.data(), pdf_buffer.size(), nullptr)); + if (!document) { + DLOG(ERROR) << "Failed to load document"; + return {}; + } + int page_count = FPDF_GetPageCount(document.get()); + if (page_count == 0) { + DLOG(ERROR) << "Got zero page count"; + return {}; + } + std::vector<uint8_t> cid_to_gid_map(CreateCidToGidMap()); + ScopedFPDFFont font(FPDFText_LoadCidType2Font( + document.get(), kPdfTtf, kPdfTtfSize, kToUnicodeCMap, + cid_to_gid_map.data(), cid_to_gid_map.size())); + CHECK(font); + for (int page_index = 0; page_index < page_count; page_index++) { + ScopedFPDFPage page(FPDF_LoadPage(document.get(), page_index)); + if (!page) { + DLOG(ERROR) << "Failed to load page"; + continue; + } + int object_count = FPDFPage_CountObjects(page.get()); + for (int object_index = 0; object_index < object_count; object_index++) { + SkBitmap bitmap = + GetImageForOcr(document.get(), page.get(), object_index); + // The object is not an image or failed to get the bitmap from the image. + if (bitmap.empty()) { + continue; + } + FPDF_PAGEOBJECT image = FPDFPage_GetObject(page.get(), object_index); + if (!image) { + DLOG(ERROR) << "Failed to get image object"; + continue; + } + auto annotation = perform_ocr_callback.Run(bitmap); + if (!annotation) { + DLOG(ERROR) << "Failed to get OCR annotation on the image"; + continue; + } + AddTextOnImage(document.get(), page.get(), font.get(), image, + std::move(annotation)); + } + if (!FPDFPage_GenerateContent(page.get())) { + DLOG(ERROR) << "Failed to generate content"; + continue; + } + } + PDFiumMemBufferFileWrite output_file_write; + if (!FPDF_SaveAsCopy(document.get(), &output_file_write, 0)) { + DLOG(ERROR) << "Failed to save the document"; + return {}; + } + return output_file_write.TakeBuffer(); +} + +} // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_searchify.h b/pdf/pdfium/pdfium_searchify.h new file mode 100644 index 0000000..4426ae2 --- /dev/null +++ b/pdf/pdfium/pdfium_searchify.h
@@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_PDFIUM_PDFIUM_SEARCHIFY_H_ +#define PDF_PDFIUM_PDFIUM_SEARCHIFY_H_ + +#include <vector> + +#include "base/containers/span.h" +#include "base/functional/callback_forward.h" +#include "services/screen_ai/public/mojom/screen_ai_service.mojom-forward.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace chrome_pdf { + +std::vector<uint8_t> PDFiumSearchify( + base::span<const uint8_t> pdf_buffer, + base::RepeatingCallback<screen_ai::mojom::VisualAnnotationPtr( + const SkBitmap& bitmap)> perform_ocr_callback); + +} // namespace chrome_pdf + +#endif // PDF_PDFIUM_PDFIUM_SEARCHIFY_H_
diff --git a/pdf/pdfium/pdfium_searchify_font.cc b/pdf/pdfium/pdfium_searchify_font.cc new file mode 100644 index 0000000..49dcde2 --- /dev/null +++ b/pdf/pdfium/pdfium_searchify_font.cc
@@ -0,0 +1,96 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/pdfium/pdfium_searchify_font.h" + +#include <cstdint> +#include <vector> + +namespace chrome_pdf { + +const uint8_t kPdfTtf[] = { + 0x0, 0x1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x80, 0x0, 0x3, 0x0, 0x20, + 0x4f, 0x53, 0x2f, 0x32, 0x56, 0xde, 0xc8, 0x94, 0x0, 0x0, 0x1, 0x28, + 0x0, 0x0, 0x0, 0x60, 0x63, 0x6d, 0x61, 0x70, 0x0, 0xa, 0x0, 0x34, + 0x0, 0x0, 0x1, 0x90, 0x0, 0x0, 0x0, 0x1e, 0x67, 0x6c, 0x79, 0x66, + 0x15, 0x22, 0x41, 0x24, 0x0, 0x0, 0x1, 0xb8, 0x0, 0x0, 0x0, 0x18, + 0x68, 0x65, 0x61, 0x64, 0xb, 0x78, 0xf1, 0x65, 0x0, 0x0, 0x0, 0xac, + 0x0, 0x0, 0x0, 0x36, 0x68, 0x68, 0x65, 0x61, 0xc, 0x2, 0x4, 0x2, + 0x0, 0x0, 0x0, 0xe4, 0x0, 0x0, 0x0, 0x24, 0x68, 0x6d, 0x74, 0x78, + 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x88, 0x0, 0x0, 0x0, 0x8, + 0x6c, 0x6f, 0x63, 0x61, 0x0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x1, 0xb0, + 0x0, 0x0, 0x0, 0x6, 0x6d, 0x61, 0x78, 0x70, 0x0, 0x4, 0x0, 0x5, + 0x0, 0x0, 0x1, 0x8, 0x0, 0x0, 0x0, 0x20, 0x6e, 0x61, 0x6d, 0x65, + 0xf2, 0xeb, 0x16, 0xda, 0x0, 0x0, 0x1, 0xd0, 0x0, 0x0, 0x0, 0x4b, + 0x70, 0x6f, 0x73, 0x74, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x2, 0x1c, + 0x0, 0x0, 0x0, 0x20, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, + 0xb0, 0x94, 0x71, 0x10, 0x5f, 0xf, 0x3c, 0xf5, 0x4, 0x7, 0x8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xcf, 0x9a, 0xfc, 0x6e, 0x0, 0x0, 0x0, 0x0, + 0xd4, 0xc3, 0xa7, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x8, 0x0, + 0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0x0, 0x0, 0x8, 0x0, 0xff, 0xff, 0x0, 0x0, 0x4, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, + 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, + 0x1, 0x90, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x47, 0x4f, 0x4f, 0x47, 0x0, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0x0, 0x0, 0x0, 0x1, + 0x0, 0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x14, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, + 0x0, 0x6, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, + 0x0, 0x0, 0x4, 0x0, 0x8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x31, 0x21, + 0x11, 0x21, 0x4, 0x0, 0xfc, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x3, + 0x0, 0x2a, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x5, 0x0, 0x16, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0xb, + 0x0, 0x16, 0x0, 0x3, 0x0, 0x1, 0x4, 0x9, 0x0, 0x5, 0x0, 0x16, + 0x0, 0x0, 0x0, 0x56, 0x0, 0x65, 0x0, 0x72, 0x0, 0x73, 0x0, 0x69, + 0x0, 0x6f, 0x0, 0x6e, 0x0, 0x20, 0x0, 0x31, 0x0, 0x2e, 0x0, 0x30, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x0, + 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + +const uint32_t kPdfTtfSize = sizeof(kPdfTtf); + +const char kToUnicodeCMap[] = R"( +/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo << + /Registry (Adobe) + /Ordering (Identity) + /Supplement 0 +>> def +/CMapName /Adobe-Identity-H def +/CMapType 2 def +1 begincodespacerange +<0000> <FFFF> +endcodespacerange +1 beginbfrange +<0000> <FFFF> <0000> +endbfrange +endcmap +CMapName currentdict /CMap defineresource pop +end +end +)"; + +std::vector<uint8_t> CreateCidToGidMap() { + std::vector<uint8_t> arr; + constexpr int kCIDToGIDMapSize = 2 * (1 << 16); + for (int i = 0; i < kCIDToGIDMapSize; i++) { + arr.push_back((i % 2) ? 1 : 0); + } + return arr; +} + +} // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_searchify_font.h b/pdf/pdfium/pdfium_searchify_font.h new file mode 100644 index 0000000..6aeef10 --- /dev/null +++ b/pdf/pdfium/pdfium_searchify_font.h
@@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PDF_PDFIUM_PDFIUM_SEARCHIFY_FONT_H_ +#define PDF_PDFIUM_PDFIUM_SEARCHIFY_FONT_H_ + +#include <cstdint> +#include <vector> + +namespace chrome_pdf { + +extern const uint8_t kPdfTtf[]; +extern const uint32_t kPdfTtfSize; + +extern const char kToUnicodeCMap[]; + +std::vector<uint8_t> CreateCidToGidMap(); + +} // namespace chrome_pdf + +#endif // PDF_PDFIUM_PDFIUM_SEARCHIFY_FONT_H_
diff --git a/remoting/host/audio_capturer_linux.cc b/remoting/host/audio_capturer_linux.cc index 5ddcaf2..6bf0c6a 100644 --- a/remoting/host/audio_capturer_linux.cc +++ b/remoting/host/audio_capturer_linux.cc
@@ -58,13 +58,16 @@ DCHECK(!callback_.is_null()); if (silence_detector_.IsSilence( - reinterpret_cast<const int16_t*>(data->data().data()), - data->data().size() / sizeof(int16_t) / AudioPipeReader::kChannels)) { + // TODO(danakj): This cast can cause UB, we should copy into integers + // or pass it as a byte span. + reinterpret_cast<const int16_t*>(data->as_string().data()), + data->as_string().size() / sizeof(int16_t) / + AudioPipeReader::kChannels)) { return; } - std::unique_ptr<AudioPacket> packet(new AudioPacket()); - packet->add_data(data->data()); + auto packet = std::make_unique<AudioPacket>(); + packet->add_data(data->as_string()); packet->set_encoding(AudioPacket::ENCODING_RAW); packet->set_sampling_rate(AudioPipeReader::kSamplingRate); packet->set_bytes_per_sample(AudioPipeReader::kBytesPerSample);
diff --git a/remoting/host/desktop_geometry.h b/remoting/host/desktop_geometry.h index 69044c5..ab347f9 100644 --- a/remoting/host/desktop_geometry.h +++ b/remoting/host/desktop_geometry.h
@@ -9,6 +9,8 @@ #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d.h" +#include <vector> + namespace remoting { using DesktopScreenId = intptr_t;
diff --git a/remoting/host/linux/audio_pipe_reader_unittest.cc b/remoting/host/linux/audio_pipe_reader_unittest.cc index 86de440..517f56e 100644 --- a/remoting/host/linux/audio_pipe_reader_unittest.cc +++ b/remoting/host/linux/audio_pipe_reader_unittest.cc
@@ -41,7 +41,7 @@ // AudioPipeReader::StreamObserver interface. void OnDataRead(scoped_refptr<base::RefCountedString> data) override { - read_data_ += data->data(); + read_data_ += data->as_string(); if (stop_at_position_ > 0 && static_cast<int>(read_data_.size()) >= stop_at_position_) { stop_at_position_ = -1;
diff --git a/remoting/host/linux/x_server_clipboard.cc b/remoting/host/linux/x_server_clipboard.cc index 0092f7f7..4af7cf18 100644 --- a/remoting/host/linux/x_server_clipboard.cc +++ b/remoting/host/linux/x_server_clipboard.cc
@@ -208,7 +208,7 @@ large_selection_property_ = x11::Atom::None; if (reply->type != x11::Atom::None) { HandleSelectionNotify(event, reply->type, reply->format, - reply->value_len, reply->value->data()); + reply->value_len, reply->value->bytes()); return; } }
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc index cf906b8..91cec9d 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -12,6 +12,7 @@ #include <linux/nbd.h> #include <linux/net.h> #include <linux/userfaultfd.h> +#include <sched.h> #include <sys/socket.h> #include <sys/syscall.h> #include <sys/types.h>
diff --git a/sandbox/policy/mac/common.sb b/sandbox/policy/mac/common.sb index 88c6174..aba1816 100644 --- a/sandbox/policy/mac/common.sb +++ b/sandbox/policy/mac/common.sb
@@ -108,14 +108,13 @@ ; Reads of signed Mach-O blobs created by the CVMS server. ; https://crbug.com/850021 (define (allow-cvms-blobs) - (if (>= os-version 1014) - (begin - (allow file-read* file-write-unlink - (prefix "/private/tmp/cvmsCodeSignObj")) - (allow file-read* - (extension "com.apple.cvms.kernel") - (prefix "/private/var/db/CVMS/cvmsCodeSignObj")) -))) + (begin + (allow file-read* file-write-unlink + (prefix "/private/tmp/cvmsCodeSignObj")) + (allow file-read* + (extension "com.apple.cvms.kernel") + (prefix "/private/var/db/CVMS/cvmsCodeSignObj")) +)) ; Allow logging for all processes. (allow file-write*
diff --git a/sandbox/policy/mac/gpu.sb b/sandbox/policy/mac/gpu.sb index 34f5f16..bcb09f0 100644 --- a/sandbox/policy/mac/gpu.sb +++ b/sandbox/policy/mac/gpu.sb
@@ -40,9 +40,7 @@ ) ; Needed for metal decoding - https://crbug.com/957217 -(if (>= os-version 1014) - (allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService")) -) +(allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService")) ; Allow access to the Apple Neural Engine for the Shape Detection API. ; https://crbug.com/1382442
diff --git a/sandbox/policy/mac/nacl_loader.sb b/sandbox/policy/mac/nacl_loader.sb index 5e4bc48..a4b3670 100644 --- a/sandbox/policy/mac/nacl_loader.sb +++ b/sandbox/policy/mac/nacl_loader.sb
@@ -36,9 +36,6 @@ (global-name "com.apple.system.notification_center") ) -(if (>= os-version 1014) - (begin - (allow sysctl-read (sysctl-name "kern.tcsm_enable")) - (allow sysctl-write (sysctl-name "kern.tcsm_enable")) - (allow sysctl-read (sysctl-name "kern.tcsm_available")) -)) +(allow sysctl-read (sysctl-name "kern.tcsm_enable")) +(allow sysctl-write (sysctl-name "kern.tcsm_enable")) +(allow sysctl-read (sysctl-name "kern.tcsm_available"))
diff --git a/sandbox/policy/mac/on_device_model_execution.sb b/sandbox/policy/mac/on_device_model_execution.sb index c392c89..2ce423d0 100644 --- a/sandbox/policy/mac/on_device_model_execution.sb +++ b/sandbox/policy/mac/on_device_model_execution.sb
@@ -12,9 +12,7 @@ (allow ipc-posix-shm) ; Needed for metal decoding - https://crbug.com/957217 -(if (>= os-version 1014) - (allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService")) -) +(allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService")) (allow mach-lookup (global-name "com.apple.system.opendirectoryd.membership") ; https://crbug.com/1126350#c5 @@ -67,4 +65,3 @@ (if (not (maybe-disable-metal-shader-cache)) (maybe-allow-metal-shader-cache-access)) -
diff --git a/sandbox/policy/mac/renderer.sb b/sandbox/policy/mac/renderer.sb index ae9acfb..92755022 100644 --- a/sandbox/policy/mac/renderer.sb +++ b/sandbox/policy/mac/renderer.sb
@@ -95,12 +95,9 @@ ) ; For V8 to use in thread calculations. -(if (>= os-version 1014) - (begin - (allow sysctl-read (sysctl-name "kern.tcsm_enable")) - (allow sysctl-write (sysctl-name "kern.tcsm_enable")) - (allow sysctl-read (sysctl-name "kern.tcsm_available")) -)) +(allow sysctl-read (sysctl-name "kern.tcsm_enable")) +(allow sysctl-write (sysctl-name "kern.tcsm_enable")) +(allow sysctl-read (sysctl-name "kern.tcsm_available")) ; This is available in 10.15+, and rolled out as a Finch experiment. (if (param-true? filter-syscalls)
diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS index fe5a10da..601ecdb 100644 --- a/services/accessibility/OWNERS +++ b/services/accessibility/OWNERS
@@ -2,4 +2,6 @@ aleventhal@chromium.org dtseng@chromium.org katie@chromium.org +lucasradaelli@google.com nektar@chromium.org +francisjp@google.com
diff --git a/services/device/hid/hid_connection_impl.cc b/services/device/hid/hid_connection_impl.cc index 3b1b56a..677b42d 100644 --- a/services/device/hid/hid_connection_impl.cc +++ b/services/device/hid/hid_connection_impl.cc
@@ -58,7 +58,7 @@ DCHECK_GE(size, 1u); std::vector<uint8_t> data; if (size > 1) { - data = std::vector<uint8_t>(buffer->front() + 1, buffer->front() + size); + data = std::vector<uint8_t>(buffer->data() + 1, buffer->data() + size); } client_->OnInputReport(/*report_id=*/buffer->data()[0], data); } @@ -80,7 +80,7 @@ } DCHECK(buffer); - std::vector<uint8_t> data(buffer->front() + 1, buffer->front() + size); + std::vector<uint8_t> data(buffer->data() + 1, buffer->data() + size); std::move(callback).Run(true, buffer->data()[0], data); } @@ -90,10 +90,9 @@ DCHECK(hid_connection_); auto io_buffer = - base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1); - io_buffer->data()[0] = report_id; - - base::ranges::copy(buffer, io_buffer->front() + 1); + base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1u); + io_buffer->as_vector().data()[0u] = report_id; + base::span(io_buffer->as_vector()).subspan(1u).copy_from(buffer); hid_connection_->Write(io_buffer, base::BindOnce(&HidConnectionImpl::OnWrite, weak_factory_.GetWeakPtr(), @@ -124,7 +123,7 @@ } DCHECK(buffer); - std::vector<uint8_t> data(buffer->front(), buffer->front() + size); + std::vector<uint8_t> data(buffer->data(), buffer->data() + size); std::move(callback).Run(true, data); } @@ -134,10 +133,9 @@ DCHECK(hid_connection_); auto io_buffer = - base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1); - io_buffer->data()[0] = report_id; - - base::ranges::copy(buffer, io_buffer->front() + 1); + base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1u); + io_buffer->as_vector()[0u] = report_id; + base::span(io_buffer->as_vector()).subspan(1u).copy_from(buffer); hid_connection_->SendFeatureReport( io_buffer,
diff --git a/services/device/hid/hid_connection_impl_unittest.cc b/services/device/hid/hid_connection_impl_unittest.cc index 3fc395b2..6c44be1 100644 --- a/services/device/hid/hid_connection_impl_unittest.cc +++ b/services/device/hid/hid_connection_impl_unittest.cc
@@ -372,7 +372,7 @@ write_future.GetCallback()); EXPECT_TRUE(write_future.Get()); ASSERT_TRUE(feature_buffer); - EXPECT_THAT(feature_buffer->data(), ElementsAre(kTestReportId)); + EXPECT_THAT(feature_buffer->as_vector(), ElementsAre(kTestReportId)); } } // namespace device
diff --git a/services/device/hid/hid_connection_linux.cc b/services/device/hid/hid_connection_linux.cc index 02c30ba..2368fee 100644 --- a/services/device/hid/hid_connection_linux.cc +++ b/services/device/hid/hid_connection_linux.cc
@@ -66,7 +66,7 @@ FROM_HERE, base::BlockingType::MAY_BLOCK); ssize_t result = - HANDLE_EINTR(write(fd_.get(), buffer->front(), buffer->size())); + HANDLE_EINTR(write(fd_.get(), buffer->data(), buffer->size())); if (result < 0) { HID_PLOG(EVENT) << "Write failed"; return false; @@ -87,7 +87,7 @@ FROM_HERE, base::BlockingType::MAY_BLOCK); int result = HANDLE_EINTR( - ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->front())); + ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data())); if (result < 0) { HID_PLOG(EVENT) << "Failed to get feature report"; return std::make_tuple(false, nullptr, 0); @@ -98,7 +98,7 @@ // Linux adds a 0 to the beginning of the data received from the device. auto copied_buffer = base::MakeRefCounted<base::RefCountedBytes>(result - 1); - memcpy(copied_buffer->front(), buffer->front() + 1, result - 1); + memcpy(copied_buffer->as_vector().data(), buffer->data() + 1, result - 1); return std::make_tuple(true, std::move(copied_buffer), result - 1); } else { return std::make_tuple(true, std::move(buffer), result); @@ -111,7 +111,7 @@ FROM_HERE, base::BlockingType::MAY_BLOCK); int result = HANDLE_EINTR( - ioctl(fd_.get(), HIDIOCSFEATURE(buffer->size()), buffer->front())); + ioctl(fd_.get(), HIDIOCSFEATURE(buffer->size()), buffer->data())); if (result < 0) { HID_PLOG(EVENT) << "Failed to send feature report"; return false; @@ -126,7 +126,7 @@ auto buffer = base::MakeRefCounted<base::RefCountedBytes>(report_buffer_size_); - uint8_t* data = buffer->front(); + uint8_t* data = buffer->as_vector().data(); size_t length = report_buffer_size_; if (!has_report_id_) { // Linux will not prefix the buffer with a report ID if report IDs are not @@ -207,7 +207,7 @@ DCHECK_GT(device_info()->max_feature_report_size(), 0u); auto buffer = base::MakeRefCounted<base::RefCountedBytes>( device_info()->max_feature_report_size() + 1); - buffer->data()[0] = report_id; + buffer->as_vector().data()[0] = report_id; auto callback_wrapper = base::BindOnce( [](ReadCallback callback,
diff --git a/services/device/hid/hid_connection_mac.cc b/services/device/hid/hid_connection_mac.cc index 641c140..c5c66c1 100644 --- a/services/device/hid/hid_connection_mac.cc +++ b/services/device/hid/hid_connection_mac.cc
@@ -101,24 +101,28 @@ void* sender, IOHIDReportType type, uint32_t report_id, - uint8_t* report_bytes, - CFIndex report_length) { + uint8_t* report_bytes_ptr, + CFIndex report_bytes_len) { HidConnectionMac* connection = static_cast<HidConnectionMac*>(context); if (result != kIOReturnSuccess) { HID_LOG(EVENT) << "Failed to read input report: " << HexErrorCode(result); return; } + // SAFETY: This function is called by macOS with the guarantee that + // `report_byte_ptr` will point to at least `report_bytes_len` many bytes. + base::span<const uint8_t> report_bytes = UNSAFE_BUFFERS(base::span( + report_bytes_ptr, base::checked_cast<size_t>(report_bytes_len))); + scoped_refptr<base::RefCountedBytes> buffer; if (connection->device_info()->has_report_id()) { // report_id is already contained in report_bytes - buffer = base::MakeRefCounted<base::RefCountedBytes>( - report_bytes, base::checked_cast<size_t>(report_length)); + buffer = base::MakeRefCounted<base::RefCountedBytes>(report_bytes); } else { buffer = base::MakeRefCounted<base::RefCountedBytes>( - (base::CheckedNumeric<size_t>(report_length) + 1).ValueOrDie()); - buffer->front()[0] = 0; - memcpy(buffer->front() + 1, report_bytes, report_length); + (base::CheckedNumeric<size_t>(report_bytes.size()) + 1u).ValueOrDie()); + buffer->as_vector()[0] = 0; + base::span(buffer->as_vector()).subspan(1u).copy_from(report_bytes); } connection->ProcessInputReport(buffer, buffer->size()); @@ -137,7 +141,7 @@ // kernel API that this is safe. IOReturn result = IOHIDDeviceGetReport(device_.get(), kIOHIDReportTypeFeature, report_id, - buffer->front(), &report_size); + buffer->as_vector().data(), &report_size); if (result == kIOReturnSuccess) { task_runner_->PostTask( FROM_HERE, base::BindOnce(&HidConnectionMac::ReturnAsyncResult, this, @@ -156,15 +160,12 @@ IOHIDReportType report_type, scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) { - uint8_t* data = buffer->front(); - size_t size = buffer->size(); - DCHECK_GE(size, 1u); - uint8_t report_id = data[0]; + auto data = base::span(buffer->as_vector()); + uint8_t report_id = data[0u]; if (report_id == 0) { // OS X only expects the first byte of the buffer to be the report ID if the // report ID is non-zero. - ++data; - --size; + data = data.subspan(1u); } // The IOHIDDevice object is shared with the UI thread and so this function @@ -172,8 +173,8 @@ // version is NOT IMPLEMENTED. I've examined the open source implementation // of this function and believe it is a simple enough wrapper around the // kernel API that this is safe. - IOReturn result = - IOHIDDeviceSetReport(device_.get(), report_type, report_id, data, size); + IOReturn result = IOHIDDeviceSetReport(device_.get(), report_type, report_id, + data.data(), data.size()); if (result == kIOReturnSuccess) { task_runner_->PostTask( FROM_HERE, base::BindOnce(&HidConnectionMac::ReturnAsyncResult, this,
diff --git a/services/device/hid/hid_connection_unittest.cc b/services/device/hid/hid_connection_unittest.cc index 951ddf92..f16b681 100644 --- a/services/device/hid/hid_connection_unittest.cc +++ b/services/device/hid/hid_connection_unittest.cc
@@ -210,9 +210,9 @@ const char kBufferSize = 9; for (char i = 0; i < 8; ++i) { auto buffer = base::MakeRefCounted<base::RefCountedBytes>(kBufferSize); - buffer->data()[0] = 0; + buffer->as_vector()[0] = 0; for (unsigned char j = 1; j < kBufferSize; ++j) { - buffer->data()[j] = i + j - 1; + buffer->as_vector()[j] = i + j - 1; } TestIoCallback write_callback; @@ -223,9 +223,9 @@ conn->Read(read_callback.GetReadCallback()); ASSERT_TRUE(read_callback.WaitForResult()); ASSERT_EQ(9UL, read_callback.size()); - ASSERT_EQ(0, read_callback.buffer()->data()[0]); + ASSERT_EQ(0, read_callback.buffer()->as_vector()[0]); for (unsigned char j = 1; j < kBufferSize; ++j) { - ASSERT_EQ(i + j - 1, read_callback.buffer()->data()[j]); + ASSERT_EQ(i + j - 1, read_callback.buffer()->as_vector()[j]); } }
diff --git a/services/device/hid/hid_connection_win.cc b/services/device/hid/hid_connection_win.cc index 87bef72d..89f80047 100644 --- a/services/device/hid/hid_connection_win.cc +++ b/services/device/hid/hid_connection_win.cc
@@ -149,9 +149,9 @@ // to the maximum output report size supported by this collection. size_t expected_size = device_info()->max_output_report_size() + 1; DCHECK(buffer->size() <= expected_size); - buffer->data().resize(expected_size); + buffer->as_vector().resize(expected_size); - uint8_t report_id = buffer->data()[0]; + uint8_t report_id = buffer->as_vector()[0]; HANDLE file_handle = GetHandleForReportId(report_id); if (!IsValidHandle(file_handle)) { HID_LOG(DEBUG) << "HID write failed due to invalid handle."; @@ -162,9 +162,9 @@ transfers_.push_back(std::make_unique<PendingHidTransfer>( buffer, base::BindOnce(&HidConnectionWin::OnWriteComplete, this, file_handle, std::move(callback)))); - transfers_.back()->TakeResultFromWindowsAPI(WriteFile( - file_handle, buffer->front(), static_cast<DWORD>(buffer->size()), NULL, - transfers_.back()->GetOverlapped())); + transfers_.back()->TakeResultFromWindowsAPI( + WriteFile(file_handle, buffer->data(), static_cast<DWORD>(buffer->size()), + NULL, transfers_.back()->GetOverlapped())); } void HidConnectionWin::PlatformGetFeatureReport(uint8_t report_id, @@ -172,7 +172,7 @@ // The first byte of the destination buffer is the report ID being requested. auto buffer = base::MakeRefCounted<base::RefCountedBytes>( device_info()->max_feature_report_size() + 1); - buffer->data()[0] = report_id; + buffer->as_vector()[0] = report_id; HANDLE file_handle = GetHandleForReportId(report_id); if (!IsValidHandle(file_handle)) { @@ -184,16 +184,16 @@ transfers_.push_back(std::make_unique<PendingHidTransfer>( buffer, base::BindOnce(&HidConnectionWin::OnReadFeatureComplete, this, file_handle, buffer, std::move(callback)))); - transfers_.back()->TakeResultFromWindowsAPI( - DeviceIoControl(file_handle, IOCTL_HID_GET_FEATURE, NULL, 0, - buffer->front(), static_cast<DWORD>(buffer->size()), NULL, - transfers_.back()->GetOverlapped())); + transfers_.back()->TakeResultFromWindowsAPI(DeviceIoControl( + file_handle, IOCTL_HID_GET_FEATURE, NULL, 0, buffer->as_vector().data(), + static_cast<DWORD>(buffer->as_vector().size()), NULL, + transfers_.back()->GetOverlapped())); } void HidConnectionWin::PlatformSendFeatureReport( scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) { - uint8_t report_id = buffer->data()[0]; + uint8_t report_id = buffer->as_vector()[0]; HANDLE file_handle = GetHandleForReportId(report_id); if (!IsValidHandle(file_handle)) { HID_LOG(DEBUG) << "HID write failed due to invalid handle."; @@ -206,10 +206,10 @@ transfers_.push_back(std::make_unique<PendingHidTransfer>( buffer, base::BindOnce(&HidConnectionWin::OnWriteComplete, this, file_handle, std::move(callback)))); - transfers_.back()->TakeResultFromWindowsAPI( - DeviceIoControl(file_handle, IOCTL_HID_SET_FEATURE, buffer->front(), - static_cast<DWORD>(buffer->size()), NULL, 0, NULL, - transfers_.back()->GetOverlapped())); + transfers_.back()->TakeResultFromWindowsAPI(DeviceIoControl( + file_handle, IOCTL_HID_SET_FEATURE, buffer->as_vector().data(), + static_cast<DWORD>(buffer->as_vector().size()), NULL, 0, NULL, + transfers_.back()->GetOverlapped())); } void HidConnectionWin::SetUpInitialReads() { @@ -227,8 +227,9 @@ buffer, base::BindOnce(&HidConnectionWin::OnReadInputReport, this, file_handle, buffer))); transfers_.back()->TakeResultFromWindowsAPI( - ReadFile(file_handle, buffer->front(), static_cast<DWORD>(buffer->size()), - NULL, transfers_.back()->GetOverlapped())); + ReadFile(file_handle, buffer->as_vector().data(), + static_cast<DWORD>(buffer->as_vector().size()), NULL, + transfers_.back()->GetOverlapped())); } void HidConnectionWin::OnReadInputReport( @@ -254,7 +255,7 @@ return; } - uint8_t report_id = buffer->data()[0]; + uint8_t report_id = buffer->as_vector()[0]; if (!IsReportProtected(report_id, HidReportType::kInput)) { // Hold a reference to |this| to prevent a callback executed by // ProcessInputReport from freeing this object.
diff --git a/services/device/usb/fake_usb_device_handle.cc b/services/device/usb/fake_usb_device_handle.cc index 8cf522b..b969ade 100644 --- a/services/device/usb/fake_usb_device_handle.cc +++ b/services/device/usb/fake_usb_device_handle.cc
@@ -88,7 +88,10 @@ } if (direction == UsbTransferDirection::INBOUND) { - memcpy(buffer->front(), &data_[position_], bytes_transferred); + auto source_data = UNSAFE_BUFFERS(base::span(data_, size_)); + base::span(buffer->as_vector()) + .first(bytes_transferred) + .copy_from(source_data.subspan(position_, bytes_transferred)); position_ += bytes_transferred; }
diff --git a/services/device/usb/mojo/device_impl.cc b/services/device/usb/mojo/device_impl.cc index 11ae873..724ceb3 100644 --- a/services/device/usb/mojo/device_impl.cc +++ b/services/device/usb/mojo/device_impl.cc
@@ -37,7 +37,7 @@ UsbTransferStatus status, scoped_refptr<base::RefCountedBytes> buffer, size_t buffer_size) { - auto data = buffer ? base::make_span(buffer->front(), buffer_size) + auto data = buffer ? base::span(*buffer).first(buffer_size) : base::span<const uint8_t>(); std::move(callback).Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status), data); @@ -59,7 +59,7 @@ [](const uint32_t& a, const UsbIsochronousPacketPtr& packet) { return a + packet->length; }); - auto data = buffer ? base::make_span(buffer->front(), buffer_size) + auto data = buffer ? base::span(*buffer).first(buffer_size) : base::span<const uint8_t>(); std::move(callback).Run(data, std::move(packets)); }
diff --git a/services/device/usb/usb_descriptors.cc b/services/device/usb/usb_descriptors.cc index f5f5e8ed..3c1d807 100644 --- a/services/device/usb/usb_descriptors.cc +++ b/services/device/usb/usb_descriptors.cc
@@ -110,7 +110,7 @@ scoped_refptr<base::RefCountedBytes> buffer, size_t length) { if (status == UsbTransferStatus::COMPLETED) { - if (!desc->Parse(base::make_span(buffer->front(), length))) { + if (!desc->Parse(base::span(*buffer).first(length))) { LOG(ERROR) << "Failed to parse configuration descriptor."; } } else { @@ -128,7 +128,7 @@ size_t length) { if (status == UsbTransferStatus::COMPLETED && length == kConfigurationDescriptorLength) { - const uint8_t* data = header->front(); + auto data = base::span<const uint8_t>(*header); uint16_t total_length = data[2] | data[3] << 8; auto buffer = base::MakeRefCounted<base::RefCountedBytes>(total_length); device_handle->ControlTransfer( @@ -157,7 +157,7 @@ } std::unique_ptr<UsbDeviceDescriptor> desc(new UsbDeviceDescriptor()); - if (!desc->Parse(base::make_span(buffer->front(), length))) { + if (!desc->Parse(base::span(*buffer).first(length))) { LOG(ERROR) << "Device descriptor parsing error."; std::move(callback).Run(nullptr); return; @@ -199,15 +199,14 @@ UsbTransferStatus status, scoped_refptr<base::RefCountedBytes> buffer, size_t length) { - std::u16string string; - if (status == UsbTransferStatus::COMPLETED && - ParseUsbStringDescriptor( - std::vector<uint8_t>(buffer->front(), buffer->front() + length), - &string)) { - std::move(callback).Run(string); - } else { - std::move(callback).Run(std::u16string()); + if (status == UsbTransferStatus::COMPLETED) { + std::u16string string; + if (ParseUsbStringDescriptor(base::span(*buffer).first(length), &string)) { + std::move(callback).Run(std::move(string)); + return; + } } + std::move(callback).Run(std::u16string()); } void ReadStringDescriptor( @@ -363,22 +362,32 @@ std::move(callback))); } -bool ParseUsbStringDescriptor(const std::vector<uint8_t>& descriptor, +bool ParseUsbStringDescriptor(base::span<const uint8_t> descriptor, std::u16string* output) { - if (descriptor.size() < 2 || descriptor[1] != kStringDescriptorType) + if (descriptor.size() < 2u) { return false; + } + + auto [header, body] = descriptor.split_at(2u); + if (header[1u] != kStringDescriptorType) { + return false; + } // Let the device return a buffer larger than the actual string but prefer the // length reported inside the descriptor. - size_t length = descriptor[0]; - length = std::min(length, descriptor.size()); - if (length < 2) + const size_t length_bytes = + std::min<size_t>(header[0u], header.size() + body.size()); + // The header's size is included in the length. If not, it's malformed. + if (length_bytes < header.size()) { return false; + } + const size_t body_bytes = length_bytes - header.size(); + const size_t body_chars = body_bytes / sizeof(char16_t); // The string is returned by the device in UTF-16LE. - *output = - std::u16string(reinterpret_cast<const char16_t*>(descriptor.data() + 2), - (length - 2) / sizeof(char16_t)); + output->resize(body_chars); + base::as_writable_byte_span(*output).copy_from( + body.first(body_chars * sizeof(char16_t))); return true; }
diff --git a/services/device/usb/usb_descriptors.h b/services/device/usb/usb_descriptors.h index 1ca2ac5..d7fdf67 100644 --- a/services/device/usb/usb_descriptors.h +++ b/services/device/usb/usb_descriptors.h
@@ -55,7 +55,7 @@ scoped_refptr<UsbDeviceHandle> device_handle, base::OnceCallback<void(std::unique_ptr<UsbDeviceDescriptor>)> callback); -bool ParseUsbStringDescriptor(const std::vector<uint8_t>& descriptor, +bool ParseUsbStringDescriptor(base::span<const uint8_t> descriptor, std::u16string* output); void ReadUsbStringDescriptors(
diff --git a/services/device/usb/usb_descriptors_unittest.cc b/services/device/usb/usb_descriptors_unittest.cc index b5b36d7..6fe3030 100644 --- a/services/device/usb/usb_descriptors_unittest.cc +++ b/services/device/usb/usb_descriptors_unittest.cc
@@ -32,7 +32,10 @@ ACTION_P2(InvokeCallback, data, length) { size_t transferred_length = std::min(length, arg6->size()); - memcpy(arg6->front(), data, transferred_length); + base::span(arg6->as_vector()) + .first(transferred_length) + .copy_from( + UNSAFE_BUFFERS(base::span(data, length)).first(transferred_length)); std::move(arg8).Run(UsbTransferStatus::COMPLETED, arg6, transferred_length); } @@ -363,8 +366,7 @@ 'o', 0, ' ', 0, 'w', 0, 'o', 0, 'r', 0, 'l', 0, 'd', 0, '!', 0}; std::u16string string; - ASSERT_TRUE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_TRUE(ParseUsbStringDescriptor(kBuffer, &string)); EXPECT_EQ(u"Hello world!", string); } @@ -372,16 +374,14 @@ // The buffer is just too darn short. static const uint8_t kBuffer[] = {0x01}; std::u16string string; - ASSERT_FALSE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_FALSE(ParseUsbStringDescriptor(kBuffer, &string)); } TEST_F(UsbDescriptorsTest, ShortStringDescriptor) { // The buffer is just too darn short. static const uint8_t kBuffer[] = {0x01, 0x03}; std::u16string string; - ASSERT_FALSE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_FALSE(ParseUsbStringDescriptor(kBuffer, &string)); } TEST_F(UsbDescriptorsTest, OddLengthStringDescriptor) { @@ -389,8 +389,7 @@ static const uint8_t kBuffer[] = {0x0d, 0x03, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, '!'}; std::u16string string; - ASSERT_TRUE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_TRUE(ParseUsbStringDescriptor(kBuffer, &string)); EXPECT_EQ(u"Hello", string); } @@ -398,8 +397,7 @@ // The string is empty. static const uint8_t kBuffer[] = {0x02, 0x03}; std::u16string string; - ASSERT_TRUE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_TRUE(ParseUsbStringDescriptor(kBuffer, &string)); EXPECT_EQ(std::u16string(), string); } @@ -407,8 +405,7 @@ // The string is only one byte. static const uint8_t kBuffer[] = {0x03, 0x03, '?'}; std::u16string string; - ASSERT_TRUE(ParseUsbStringDescriptor( - std::vector<uint8_t>(kBuffer, kBuffer + sizeof(kBuffer)), &string)); + ASSERT_TRUE(ParseUsbStringDescriptor(kBuffer, &string)); EXPECT_EQ(std::u16string(), string); }
diff --git a/services/device/usb/usb_device_handle_impl.cc b/services/device/usb/usb_device_handle_impl.cc index c556bd1..3bb1061 100644 --- a/services/device/usb/usb_device_handle_impl.cc +++ b/services/device/usb/usb_device_handle_impl.cc
@@ -273,10 +273,11 @@ return nullptr; } - libusb_fill_control_setup(buffer->front(), type, request, value, index, - length); + libusb_fill_control_setup(buffer->as_vector().data(), type, request, value, + index, length); libusb_fill_control_transfer(transfer->platform_transfer_, - device_handle->handle(), buffer->front(), + device_handle->handle(), + buffer->as_vector().data(), &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), timeout); @@ -303,10 +304,11 @@ return nullptr; } - libusb_fill_bulk_transfer( - transfer->platform_transfer_, device_handle->handle(), endpoint, - buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback, - transfer.get(), timeout); + libusb_fill_bulk_transfer(transfer->platform_transfer_, + device_handle->handle(), endpoint, + buffer->as_vector().data(), length, + &UsbDeviceHandleImpl::Transfer::PlatformCallback, + transfer.get(), timeout); return transfer; } @@ -333,8 +335,9 @@ libusb_fill_interrupt_transfer( transfer->platform_transfer_, device_handle->handle(), endpoint, - buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback, - transfer.get(), timeout); + buffer->as_vector().data(), length, + &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(), + timeout); return transfer; } @@ -363,7 +366,7 @@ libusb_fill_iso_transfer( transfer->platform_transfer_, device_handle->handle(), endpoint, - buffer->front(), static_cast<int>(length), num_packets, + buffer->as_vector().data(), static_cast<int>(length), num_packets, &Transfer::PlatformCallback, transfer.get(), timeout); for (size_t i = 0; i < packet_lengths.size(); ++i) @@ -445,8 +448,9 @@ if (length_ >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) { auto resized_buffer = base::MakeRefCounted<base::RefCountedBytes>(actual_length); - memcpy(resized_buffer->front(), - buffer_->front() + LIBUSB_CONTROL_SETUP_SIZE, actual_length); + base::span(resized_buffer->as_vector()) + .copy_from(base::span(*buffer_).subspan(LIBUSB_CONTROL_SETUP_SIZE, + actual_length)); buffer_ = resized_buffer; } } @@ -701,8 +705,9 @@ const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + buffer->size(); auto resized_buffer = base::MakeRefCounted<base::RefCountedBytes>(resized_length); - memcpy(resized_buffer->front() + LIBUSB_CONTROL_SETUP_SIZE, buffer->front(), - buffer->size()); + base::span(resized_buffer->as_vector()) + .subspan(LIBUSB_CONTROL_SETUP_SIZE) + .copy_from(base::span(*buffer)); std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer( this, CreateRequestType(direction, request_type, recipient), request,
diff --git a/services/device/usb/usb_device_handle_mac.cc b/services/device/usb/usb_device_handle_mac.cc index 9c30e80..8ee09f51 100644 --- a/services/device/usb/usb_device_handle_mac.cc +++ b/services/device/usb/usb_device_handle_mac.cc
@@ -449,7 +449,7 @@ device_request.wIndex = index; device_request.bmRequestType = CreateRequestType(direction, request_type, recipient); - device_request.pData = buffer->front_as<void*>(); + device_request.pData = buffer->as_vector().data(); device_request.wLength = static_cast<uint16_t>(buffer->size()); device_request.completionTimeout = timeout; device_request.noDataTimeout = timeout; @@ -550,7 +550,7 @@ kr = (*interface_interface.get()) ->ReadIsochPipeAsync(interface_interface.get(), endpoint_it->second.pipe_reference, - buffer->front_as<void*>(), bus_frame, + buffer->as_vector().data(), bus_frame, static_cast<uint32_t>(packet_lengths.size()), transfer->frame_list.data(), &AsyncIoCallback, reinterpret_cast<void*>(transfer_data)); @@ -636,7 +636,7 @@ kr = (*interface_interface.get()) ->WriteIsochPipeAsync(interface_interface.get(), endpoint_it->second.pipe_reference, - buffer->front_as<void*>(), bus_frame, + buffer->as_vector().data(), bus_frame, static_cast<uint32_t>(packet_lengths.size()), transfer->frame_list.data(), &AsyncIoCallback, reinterpret_cast<void*>(transfer_data)); @@ -749,7 +749,7 @@ auto result = transfers_.insert(std::move(transfer)); IOReturn kr = (*interface_interface.get()) ->ReadPipeAsyncTO(interface_interface.get(), pipe_reference, - buffer->front_as<void*>(), + buffer->as_vector().data(), static_cast<uint32_t>(buffer->size()), timeout, timeout, &AsyncIoCallback, reinterpret_cast<void*>(transfer_data)); @@ -773,7 +773,7 @@ IOReturn kr = (*interface_interface.get()) ->WritePipeAsyncTO(interface_interface.get(), pipe_reference, - buffer->front_as<void*>(), + buffer->as_vector().data(), static_cast<uint32_t>(buffer->size()), timeout, timeout, &AsyncIoCallback, reinterpret_cast<void*>(transfer_data)); @@ -795,7 +795,7 @@ auto result = transfers_.insert(std::move(transfer)); IOReturn kr = (*interface_interface.get()) ->ReadPipeAsync(interface_interface.get(), pipe_reference, - buffer->front_as<void*>(), + buffer->as_vector().data(), static_cast<uint32_t>(buffer->size()), &AsyncIoCallback, reinterpret_cast<void*>(transfer_data)); @@ -816,7 +816,7 @@ auto result = transfers_.insert(std::move(transfer)); IOReturn kr = (*interface_interface.get()) ->WritePipeAsync(interface_interface.get(), pipe_reference, - buffer->front_as<void*>(), + buffer->as_vector().data(), static_cast<uint32_t>(buffer->size()), &AsyncIoCallback, reinterpret_cast<void*>(transfer_data));
diff --git a/services/device/usb/usb_device_handle_unittest.cc b/services/device/usb/usb_device_handle_unittest.cc index 3576b69..71624c1 100644 --- a/services/device/usb/usb_device_handle_unittest.cc +++ b/services/device/usb/usb_device_handle_unittest.cc
@@ -164,7 +164,7 @@ base::MakeRefCounted<base::RefCountedBytes>(in_buffer->size()); TestCompletionCallback out_completion; for (size_t i = 0; i < out_buffer->size(); ++i) { - out_buffer->data()[i] = i; + out_buffer->as_vector()[i] = i; } handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x01, out_buffer, @@ -230,7 +230,7 @@ base::MakeRefCounted<base::RefCountedBytes>(in_buffer->size()); TestCompletionCallback out_completion; for (size_t i = 0; i < out_buffer->size(); ++i) { - out_buffer->data()[i] = i; + out_buffer->as_vector()[i] = i; } handle->GenericTransfer(UsbTransferDirection::OUTBOUND, 0x02, out_buffer,
diff --git a/services/device/usb/usb_device_handle_usbfs.cc b/services/device/usb/usb_device_handle_usbfs.cc index ec4a06a..87c7f6ca 100644 --- a/services/device/usb/usb_device_handle_usbfs.cc +++ b/services/device/usb/usb_device_handle_usbfs.cc
@@ -96,16 +96,18 @@ scoped_refptr<base::RefCountedBytes> original_buffer) { auto new_buffer = base::MakeRefCounted<base::RefCountedBytes>( original_buffer->size() + sizeof(usb_ctrlrequest)); - usb_ctrlrequest* setup = new_buffer->front_as<usb_ctrlrequest>(); - setup->bRequestType = ConvertEndpointDirection(direction) | - ConvertRequestType(request_type) | - ConvertRecipient(recipient); - setup->bRequest = request; - setup->wValue = value; - setup->wIndex = index; - setup->wLength = original_buffer->size(); - memcpy(new_buffer->front() + sizeof(usb_ctrlrequest), - original_buffer->front(), original_buffer->size()); + usb_ctrlrequest setup; + setup.bRequestType = ConvertEndpointDirection(direction) | + ConvertRequestType(request_type) | + ConvertRecipient(recipient); + setup.bRequest = request; + setup.wValue = value; + setup.wIndex = index; + setup.wLength = original_buffer->size(); + auto [setup_span, remain] = + base::span(new_buffer->as_vector()).split_at<sizeof(setup)>(); + setup_span.copy_from(base::byte_span_from_ref(setup)); + remain.copy_from(base::span(*original_buffer)); return new_buffer; } @@ -373,19 +375,19 @@ } UsbDeviceHandleUsbfs::Transfer::Transfer( - scoped_refptr<base::RefCountedBytes> buffer, + scoped_refptr<base::RefCountedBytes> in_buffer, TransferCallback callback) - : buffer(buffer), callback(std::move(callback)) { + : buffer(std::move(in_buffer)), callback(std::move(callback)) { urb.usercontext = this; - urb.buffer = buffer->front(); + urb.buffer = buffer->as_vector().data(); } UsbDeviceHandleUsbfs::Transfer::Transfer( - scoped_refptr<base::RefCountedBytes> buffer, + scoped_refptr<base::RefCountedBytes> in_buffer, IsochronousTransferCallback callback) - : buffer(buffer), isoc_callback(std::move(callback)) { + : buffer(std::move(in_buffer)), isoc_callback(std::move(callback)) { urb.usercontext = this; - urb.buffer = buffer->front(); + urb.buffer = buffer->as_vector().data(); } UsbDeviceHandleUsbfs::Transfer::~Transfer() = default; @@ -624,8 +626,9 @@ direction, request_type, recipient, request, value, index, buffer); transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL; transfer->urb.endpoint = 0; - transfer->urb.buffer = transfer->control_transfer_buffer->front(); - transfer->urb.buffer_length = transfer->control_transfer_buffer->size(); + transfer->urb.buffer = transfer->control_transfer_buffer->as_vector().data(); + transfer->urb.buffer_length = + transfer->control_transfer_buffer->as_vector().size(); // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported // by USBDEVFS_REAPURBNDELAY. @@ -917,9 +920,12 @@ if (transfer->urb.status == 0 && transfer->urb.type == USBDEVFS_URB_TYPE_CONTROL) { // Copy the result of the control transfer back into the original buffer. - memcpy(transfer->buffer->front(), - transfer->control_transfer_buffer->front() + 8, - transfer->urb.actual_length); + const auto actual_length = + base::checked_cast<size_t>(transfer->urb.actual_length); + base::span(transfer->buffer->as_vector()) + .first(actual_length) + .copy_from(base::span(*transfer->control_transfer_buffer) + .subspan(8u, actual_length)); } transfer->RunCallback(ConvertTransferResult(-transfer->urb.status),
diff --git a/services/device/usb/usb_device_handle_win.cc b/services/device/usb/usb_device_handle_win.cc index 9164a05..c563d7ae 100644 --- a/services/device/usb/usb_device_handle_win.cc +++ b/services/device/usb/usb_device_handle_win.cc
@@ -461,20 +461,23 @@ ((value >> 8) == USB_BOS_DESCRIPTOR_TYPE)) { size_t size = sizeof(USB_DESCRIPTOR_REQUEST) + buffer->size(); auto request_buffer = base::MakeRefCounted<base::RefCountedBytes>(size); - USB_DESCRIPTOR_REQUEST* descriptor_request = - request_buffer->front_as<USB_DESCRIPTOR_REQUEST>(); - descriptor_request->ConnectionIndex = device_->port_number(); - descriptor_request->SetupPacket.bmRequest = BMREQUEST_DEVICE_TO_HOST; - descriptor_request->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; - descriptor_request->SetupPacket.wValue = value; - descriptor_request->SetupPacket.wIndex = index; - descriptor_request->SetupPacket.wLength = buffer->size(); + USB_DESCRIPTOR_REQUEST descriptor_request; + descriptor_request.ConnectionIndex = device_->port_number(); + descriptor_request.SetupPacket.bmRequest = BMREQUEST_DEVICE_TO_HOST; + descriptor_request.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + descriptor_request.SetupPacket.wValue = value; + descriptor_request.SetupPacket.wIndex = index; + descriptor_request.SetupPacket.wLength = buffer->size(); + base::span(request_buffer->as_vector()) + .first<sizeof(USB_DESCRIPTOR_REQUEST)>() + .copy_from(base::byte_span_from_ref(descriptor_request)); blocking_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&DeviceIoControlBlocking, hub_handle_.Get(), IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - request_buffer->front(), size), + request_buffer->as_vector().data(), + request_buffer->as_vector().size()), base::BindOnce(&UsbDeviceHandleWin::GotDescriptorFromNodeConnection, weak_factory_.GetWeakPtr(), std::move(callback), request_buffer, buffer)); @@ -560,13 +563,13 @@ Request* request = MakeRequest(interface); BOOL result; if (direction == UsbTransferDirection::INBOUND) { - result = WinUsb_ReadPipe(interface->handle.Get(), endpoint_address, - buffer->front(), buffer->size(), nullptr, - request->overlapped()); + result = WinUsb_ReadPipe( + interface->handle.Get(), endpoint_address, buffer->as_vector().data(), + buffer->as_vector().size(), nullptr, request->overlapped()); } else { - result = WinUsb_WritePipe(interface->handle.Get(), endpoint_address, - buffer->front(), buffer->size(), nullptr, - request->overlapped()); + result = WinUsb_WritePipe( + interface->handle.Get(), endpoint_address, buffer->as_vector().data(), + buffer->as_vector().size(), nullptr, request->overlapped()); } DWORD last_error = GetLastError(); request->MaybeStartWatching( @@ -976,7 +979,8 @@ Request* control_request = MakeRequest(interface); BOOL result = WinUsb_ControlTransfer( - interface->handle.Get(), setup, buffer->front(), buffer->size(), + interface->handle.Get(), setup, buffer->as_vector().data(), + buffer->as_vector().size(), /*LengthTransferred=*/nullptr, control_request->overlapped()); DWORD last_error = GetLastError(); control_request->MaybeStartWatching( @@ -1031,8 +1035,11 @@ size_t bytes_transferred = std::min(sizeof(USB_DEVICE_DESCRIPTOR), buffer->size()); - memcpy(buffer->front(), &node_connection_info->DeviceDescriptor, - bytes_transferred); + base::span(buffer->as_vector()) + .first(bytes_transferred) + .copy_from( + base::byte_span_from_ref(node_connection_info->DeviceDescriptor) + .first(bytes_transferred)); std::move(callback).Run(UsbTransferStatus::COMPLETED, buffer, bytes_transferred); } @@ -1063,9 +1070,11 @@ result_and_bytes_transferred.second - sizeof(USB_DESCRIPTOR_REQUEST); bytes_transferred = std::min(bytes_transferred, original_buffer->size()); - memcpy(original_buffer->front(), - request_buffer->front() + sizeof(USB_DESCRIPTOR_REQUEST), - bytes_transferred); + base::span(original_buffer->as_vector()) + .first(bytes_transferred) + .copy_from( + base::span(*request_buffer) + .subspan(sizeof(USB_DESCRIPTOR_REQUEST), bytes_transferred)); std::move(callback).Run(UsbTransferStatus::COMPLETED, original_buffer, bytes_transferred); }
diff --git a/services/device/usb/webusb_descriptors.cc b/services/device/usb/webusb_descriptors.cc index 805464b..62f7da5 100644 --- a/services/device/usb/webusb_descriptors.cc +++ b/services/device/usb/webusb_descriptors.cc
@@ -63,7 +63,7 @@ } GURL url; - ParseWebUsbUrlDescriptor(base::make_span(buffer->front(), length), &url); + ParseWebUsbUrlDescriptor(base::make_span(buffer->data(), length), &url); std::move(callback).Run(url); } @@ -80,7 +80,7 @@ WebUsbPlatformCapabilityDescriptor descriptor; if (!descriptor.ParseFromBosDescriptor( - base::make_span(buffer->front(), length))) { + base::make_span(buffer->data(), length))) { std::move(callback).Run(std::nullopt); return; } @@ -99,7 +99,7 @@ return; } - const uint8_t* data = buffer->front(); + const uint8_t* data = buffer->data(); uint16_t new_length = data[2] | (data[3] << 8); auto new_buffer = base::MakeRefCounted<base::RefCountedBytes>(new_length); device_handle->ControlTransfer(
diff --git a/services/device/usb/webusb_descriptors_unittest.cc b/services/device/usb/webusb_descriptors_unittest.cc index e338842..6f88256 100644 --- a/services/device/usb/webusb_descriptors_unittest.cc +++ b/services/device/usb/webusb_descriptors_unittest.cc
@@ -53,7 +53,10 @@ ACTION_P2(InvokeCallback, data, length) { size_t transferred_length = std::min(length, arg6->size()); - memcpy(arg6->front(), data, transferred_length); + base::span(arg6->as_vector()) + .first(transferred_length) + .copy_from( + UNSAFE_BUFFERS(base::span(data, length)).first(transferred_length)); std::move(arg8).Run(UsbTransferStatus::COMPLETED, arg6, transferred_length); }
diff --git a/services/network/ip_protection/ip_protection_proxy_delegate.cc b/services/network/ip_protection/ip_protection_proxy_delegate.cc index 4f08bb8..ebaaeb7d3 100644 --- a/services/network/ip_protection/ip_protection_proxy_delegate.cc +++ b/services/network/ip_protection/ip_protection_proxy_delegate.cc
@@ -154,17 +154,20 @@ } } } - // Final fallback is to DIRECT. - auto direct_proxy_chain = net::ProxyChain::Direct(); - if (net::features::kIpPrivacyDirectOnly.Get()) { - // To enable measuring how much traffic would be proxied (for - // experimentation and planning purposes), mark the direct - // proxy chain as being for IP Protection when `kIpPrivacyDirectOnly` is - // true. When it is false, we only care about traffic that actually went - // through the IP Protection proxies, so don't set this flag. - direct_proxy_chain = net::ProxyChain::ForIpProtection({}); + + if (net::features::kIpPrivacyFallbackToDirect.Get()) { + // Final fallback is to DIRECT. + auto direct_proxy_chain = net::ProxyChain::Direct(); + if (net::features::kIpPrivacyDirectOnly.Get()) { + // To enable measuring how much traffic would be proxied (for + // experimentation and planning purposes), mark the direct + // proxy chain as being for IP Protection when `kIpPrivacyDirectOnly` is + // true. When it is false, we only care about traffic that actually went + // through the IP Protection proxies, so don't set this flag. + direct_proxy_chain = net::ProxyChain::ForIpProtection({}); + } + proxy_list.AddProxyChain(std::move(direct_proxy_chain)); } - proxy_list.AddProxyChain(std::move(direct_proxy_chain)); if (VLOG_IS_ON(3)) { dvlog(base::StrCat({"setting proxy list (before deprioritization) to ",
diff --git a/services/network/network_service_memory_cache.cc b/services/network/network_service_memory_cache.cc index 2536256..b83e98c 100644 --- a/services/network/network_service_memory_cache.cc +++ b/services/network/network_service_memory_cache.cc
@@ -135,8 +135,8 @@ if (decision == orb::ResponseAnalyzer::Decision::kSniffMore) { const size_t size = std::min(static_cast<size_t>(net::kMaxBytesToSniff), content.size()); - decision = analyzer->Sniff( - std::string_view(reinterpret_cast<const char*>(content.front()), size)); + decision = + analyzer->Sniff(base::as_string_view(base::span(content).first(size))); if (decision == orb::ResponseAnalyzer::Decision::kSniffMore) { decision = analyzer->HandleEndOfSniffableResponseBody(); }
diff --git a/services/network/network_service_memory_cache_url_loader.cc b/services/network/network_service_memory_cache_url_loader.cc index fcb2249..e98edb3 100644 --- a/services/network/network_service_memory_cache_url_loader.cc +++ b/services/network/network_service_memory_cache_url_loader.cc
@@ -167,9 +167,9 @@ break; } - MojoResult result = - producer_handle_->WriteData(content_->data().data() + write_position_, - &write_size, MOJO_WRITE_DATA_FLAG_NONE); + MojoResult result = producer_handle_->WriteData( + content_->as_vector().data() + write_position_, &write_size, + MOJO_WRITE_DATA_FLAG_NONE); if (result == MOJO_RESULT_SHOULD_WAIT) { producer_handle_watcher_->ArmOrNotify(); break; @@ -192,8 +192,8 @@ if (net_log_.IsCapturing()) { net_log_.AddByteTransferEvent( net::NetLogEventType::IN_MEMORY_CACHE_BYTES_READ, total_write_size, - reinterpret_cast<const char*>(content_->data().data() + - original_write_position)); + base::as_chars(base::span(*content_).subspan(original_write_position)) + .data()); } if (write_completed) {
diff --git a/services/network/web_bundle/web_bundle_chunked_buffer.cc b/services/network/web_bundle/web_bundle_chunked_buffer.cc index e2592af..8d3da169c 100644 --- a/services/network/web_bundle/web_bundle_chunked_buffer.cc +++ b/services/network/web_bundle/web_bundle_chunked_buffer.cc
@@ -81,7 +81,7 @@ } const uint8_t* WebBundleChunkedBuffer::Chunk::data() const { - return bytes_->data().data(); + return bytes_->data(); } WebBundleChunkedBuffer::WebBundleChunkedBuffer() = default;
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc index 2e864af..9240f7c 100644 --- a/services/on_device_model/ml/on_device_model_executor.cc +++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -409,6 +409,7 @@ language_detector_, adaptation_id); } +DISABLE_CFI_DLSYM on_device_model::mojom::SafetyInfoPtr OnDeviceModelExecutor::ClassifyTextSafety( const std::string& text) { if (!chrome_ml_->api().ClassifyTextSafety) {
diff --git a/services/tracing/public/cpp/perfetto/producer_test_utils.cc b/services/tracing/public/cpp/perfetto/producer_test_utils.cc index b22c485..878131fc 100644 --- a/services/tracing/public/cpp/perfetto/producer_test_utils.cc +++ b/services/tracing/public/cpp/perfetto/producer_test_utils.cc
@@ -271,7 +271,8 @@ const scoped_refptr<base::RefCountedString>& chunk, bool has_more_events) { perfetto::protos::Trace trace; - bool ok = trace.ParseFromArray(chunk->data().data(), chunk->data().size()); + auto chunk_data = base::span(*chunk); + bool ok = trace.ParseFromArray(chunk_data.data(), chunk_data.size()); DCHECK(ok); for (const auto& packet : trace.packet()) { // Filter out packets from the tracing service.
diff --git a/services/tracing/public/cpp/perfetto/system_trace_writer.h b/services/tracing/public/cpp/perfetto/system_trace_writer.h index 5fb7220..e5e30c2a 100644 --- a/services/tracing/public/cpp/perfetto/system_trace_writer.h +++ b/services/tracing/public/cpp/perfetto/system_trace_writer.h
@@ -29,7 +29,7 @@ inline const std::string& GetString( const scoped_refptr<base::RefCountedString>& string) { - return string->data(); + return string->as_string(); } } // namespace internal
diff --git a/services/video_effects/BUILD.gn b/services/video_effects/BUILD.gn index f90038b6..ae63703 100644 --- a/services/video_effects/BUILD.gn +++ b/services/video_effects/BUILD.gn
@@ -14,6 +14,8 @@ sources = [ "video_effects_processor_impl.cc", + "video_effects_processor_webgpu.cc", + "video_effects_processor_webgpu.h", "video_effects_service_impl.cc", "viz_gpu_channel_host_provider.cc", ] @@ -27,6 +29,13 @@ "//services/video_effects/public/mojom:mojom", "//services/viz/public/cpp/gpu:gpu", ] + + deps = [ + "//gpu/command_buffer/client:webgpu_interface", + "//gpu/webgpu:common", + "//third_party/dawn/src/dawn:cpp", + "//third_party/dawn/src/dawn:proc", + ] } buildflag_header("buildflags") {
diff --git a/services/video_effects/DEPS b/services/video_effects/DEPS index 35aa7a7..8bdb7823 100644 --- a/services/video_effects/DEPS +++ b/services/video_effects/DEPS
@@ -1,13 +1,16 @@ include_rules = [ "+components/viz/common/gpu", "+content/public/common", + "+gpu/command_buffer/client", "+gpu/command_buffer/common", "+gpu/ipc/client", + "+gpu/webgpu", "+media/base", "+media/capture/mojom", "+services/viz/public/cpp/gpu", "+services/viz/public/mojom", "+services/video_effects/public/mojom", + "+third_party/dawn/include/dawn", ] specific_include_rules = {
diff --git a/services/video_effects/video_effects_processor_impl.cc b/services/video_effects/video_effects_processor_impl.cc index b5ba394..168844ae 100644 --- a/services/video_effects/video_effects_processor_impl.cc +++ b/services/video_effects/video_effects_processor_impl.cc
@@ -4,6 +4,8 @@ #include "services/video_effects/video_effects_processor_impl.h" +#include <memory> + #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/types/cxx23_to_underlying.h" @@ -12,6 +14,7 @@ #include "gpu/ipc/client/gpu_channel_host.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "services/video_effects/public/mojom/video_effects_processor.mojom.h" +#include "services/video_effects/video_effects_processor_webgpu.h" #include "services/video_effects/video_effects_service_impl.h" #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" @@ -115,25 +118,24 @@ // In order to create a Video Effects Processor, we will need to have 2 // distinct context providers - one for WebGPUInterface, and one for // RasterInterface. We will also need a SharedImageInterface. + auto gpu_channel_host = gpu_channel_host_provider_->GetGpuChannelHost(); + CHECK(gpu_channel_host); + scoped_refptr<viz::ContextProviderCommandBuffer> webgpu_context_provider = - CreateAndBindContextProvider( - gpu_channel_host_provider_->GetGpuChannelHost(), - gpu::CONTEXT_TYPE_WEBGPU); + CreateAndBindContextProvider(gpu_channel_host, gpu::CONTEXT_TYPE_WEBGPU); if (!webgpu_context_provider) { return false; } scoped_refptr<viz::ContextProviderCommandBuffer> raster_interface_context_provider = CreateAndBindContextProvider( - gpu_channel_host_provider_->GetGpuChannelHost(), - gpu::CONTEXT_TYPE_OPENGLES2); + gpu_channel_host, gpu::CONTEXT_TYPE_OPENGLES2); if (!raster_interface_context_provider) { return false; } scoped_refptr<gpu::ClientSharedImageInterface> shared_image_interface = - gpu_channel_host_provider_->GetGpuChannelHost() - ->CreateClientSharedImageInterface(); + gpu_channel_host->CreateClientSharedImageInterface(); if (!shared_image_interface) { return false; } @@ -145,7 +147,12 @@ raster_interface_context_provider_->AddObserver(this); shared_image_interface = std::move(shared_image_interface); - return true; + processor_webgpu_ = std::make_unique<VideoEffectsProcessorWebGpu>( + webgpu_context_provider_, + base::BindOnce( + base::BindOnce(&VideoEffectsProcessorImpl::OnWebGpuProcessorError, + weak_ptr_factory_.GetWeakPtr()))); + return processor_webgpu_->Initialize(); } void VideoEffectsProcessorImpl::OnContextLost() { @@ -153,6 +160,11 @@ initialized_ = false; + // Before trying to reinitialize GPU state, we should first tear down the + // current state. + // TODO(bialpio): consider extracting the entire GPU state into a helper + // class that can just be nulled out. + if (webgpu_context_provider_) { webgpu_context_provider_->RemoveObserver(this); } @@ -164,21 +176,19 @@ } raster_interface_context_provider_.reset(); - shared_image_interface_.reset(); + processor_webgpu_.reset(); ++num_context_losses_; if (ContextLossesExceedThreshold(num_context_losses_)) { - if (on_unrecoverable_error_) { - std::move(on_unrecoverable_error_).Run(); - } + MaybeCallOnUnrecoverableError(); return; } const bool gpu_initialized = InitializeGpuState(); - if (!gpu_initialized && on_unrecoverable_error_) { - std::move(on_unrecoverable_error_).Run(); + if (!gpu_initialized) { + MaybeCallOnUnrecoverableError(); } } @@ -191,8 +201,20 @@ processor_receiver_.reset(); manager_remote_.reset(); - if (on_unrecoverable_error_) { - std::move(on_unrecoverable_error_).Run(); + MaybeCallOnUnrecoverableError(); +} + +void VideoEffectsProcessorImpl::OnWebGpuProcessorError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + processor_webgpu_.reset(); + + processor_webgpu_ = std::make_unique<VideoEffectsProcessorWebGpu>( + webgpu_context_provider_, + base::BindOnce(&VideoEffectsProcessorImpl::OnWebGpuProcessorError, + weak_ptr_factory_.GetWeakPtr())); + if (!processor_webgpu_->Initialize()) { + MaybeCallOnUnrecoverableError(); } } @@ -219,4 +241,10 @@ mojom::PostProcessResult::NewError(mojom::PostProcessError::kUnknown)); } +void VideoEffectsProcessorImpl::MaybeCallOnUnrecoverableError() { + if (on_unrecoverable_error_) { + std::move(on_unrecoverable_error_).Run(); + } +} + } // namespace video_effects
diff --git a/services/video_effects/video_effects_processor_impl.h b/services/video_effects/video_effects_processor_impl.h index 05061821..1cf4b75 100644 --- a/services/video_effects/video_effects_processor_impl.h +++ b/services/video_effects/video_effects_processor_impl.h
@@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "components/viz/common/gpu/context_lost_observer.h" +#include "components/viz/common/gpu/raster_context_provider.h" #include "media/base/video_types.h" #include "media/capture/mojom/video_capture_buffer.mojom-forward.h" #include "media/capture/mojom/video_effects_manager.mojom.h" @@ -18,6 +19,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/video_effects/public/mojom/video_effects_processor.mojom.h" +#include "services/video_effects/video_effects_processor_webgpu.h" #include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" namespace video_effects { @@ -71,14 +73,22 @@ // viz::ContextLostObserver: void OnContextLost() override; - // Helper, registered as a disconnect handler for `manager_remote_` and - // `processor_receiver_`. + // Registered as a disconnect handler for `manager_remote_` and + // `processor_receiver_`. Calling it will cause this processor to become + // defunct as we cannot work without functional mojo connections. void OnMojoDisconnected(); - // Helper, initializes GPU state (context providers and shared image - // interface). + // Passed into `processor_webgpu_` as its unrecoverable error callback. + // It will attempt to recreate the `processor_webgpu_` instance and + // reinitialize it. + void OnWebGpuProcessorError(); + + // Initializes GPU state (context providers and shared image interface). bool InitializeGpuState(); + // Calls `on_unrecoverable_error_` if it's set. + void MaybeCallOnUnrecoverableError(); + bool initialized_ = false; mojo::Remote<media::mojom::VideoEffectsManager> manager_remote_; @@ -86,21 +96,22 @@ std::unique_ptr<GpuChannelHostProvider> gpu_channel_host_provider_; + // Called when this processor enters a defunct state. + base::OnceClosure on_unrecoverable_error_; + // GPU state. Will be created in `Initialize()`, and should be recreated // on context loss. scoped_refptr<viz::ContextProviderCommandBuffer> webgpu_context_provider_; - scoped_refptr<viz::ContextProviderCommandBuffer> - raster_interface_context_provider_; + scoped_refptr<viz::RasterContextProvider> raster_interface_context_provider_; scoped_refptr<gpu::ClientSharedImageInterface> shared_image_interface_; + std::unique_ptr<VideoEffectsProcessorWebGpu> processor_webgpu_; + // We'll keep track of how many context losses we've experienced. If this // number is too high, we'll make this processor defunct, assuming that // it is causing some instability with GPU service. int num_context_losses_ = 0; - // Called when this processor enters a defunct state. - base::OnceClosure on_unrecoverable_error_; - SEQUENCE_CHECKER(sequence_checker_); // Must be last:
diff --git a/services/video_effects/video_effects_processor_webgpu.cc b/services/video_effects/video_effects_processor_webgpu.cc new file mode 100644 index 0000000..b8be401d --- /dev/null +++ b/services/video_effects/video_effects_processor_webgpu.cc
@@ -0,0 +1,201 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/video_effects/video_effects_processor_webgpu.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/strings/stringprintf.h" +#include "gpu/command_buffer/client/webgpu_interface.h" +#include "gpu/webgpu/callback.h" +#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h" +#include "third_party/dawn/include/dawn/dawn_proc.h" +#include "third_party/dawn/include/dawn/dawn_proc_table.h" +#include "third_party/dawn/include/dawn/webgpu.h" +#include "third_party/dawn/include/dawn/webgpu_cpp.h" +#include "third_party/dawn/include/dawn/webgpu_cpp_print.h" + +namespace video_effects { + +VideoEffectsProcessorWebGpu::VideoEffectsProcessorWebGpu( + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + base::OnceClosure on_unrecoverable_error) + : context_provider_(std::move(context_provider)), + on_unrecoverable_error_(std::move(on_unrecoverable_error)) { + CHECK(context_provider_); + CHECK(context_provider_->WebGPUInterface()); +} + +VideoEffectsProcessorWebGpu::~VideoEffectsProcessorWebGpu() = default; + +bool VideoEffectsProcessorWebGpu::Initialize() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + gpu::webgpu::WebGPUInterface* webgpu_interface = + context_provider_->WebGPUInterface(); + + scoped_refptr<gpu::webgpu::APIChannel> webgpu_api_channel = + webgpu_interface->GetAPIChannel(); + + // C++ wrapper for WebGPU requires us to install a proc table globally per + // process or per thread. Here, we install them per-process. + const DawnProcTable& procs = webgpu_api_channel->GetProcs(); + dawnProcSetProcs(&procs); + + // Required to create a device. Setting a synthetic token here means that + // blob cache will be disabled in Dawn, since the mapping that is going to + // be queried will return an empty string. For more details see + // `GpuProcessHost::GetIsolationKey()`. + webgpu_interface->SetWebGPUExecutionContextToken( + blink::WebGPUExecutionContextToken(blink::DedicatedWorkerToken{})); + + WGPUInstance webgpu_c_instance = webgpu_api_channel->GetWGPUInstance(); + instance_ = wgpu::Instance(webgpu_c_instance); + + auto* request_adapter_callback = gpu::webgpu::BindWGPUOnceCallback( + [](base::WeakPtr<VideoEffectsProcessorWebGpu> processor, + WGPURequestAdapterStatus status, WGPUAdapter adapter, + char const* message) { + if (processor) { + processor->OnRequestAdapter(status, adapter, message); + } + }, + weak_ptr_factory_.GetWeakPtr()); + instance_.RequestAdapter(nullptr, request_adapter_callback->UnboundCallback(), + request_adapter_callback->AsUserdata()); + EnsureFlush(); + + return true; +} + +void VideoEffectsProcessorWebGpu::OnRequestAdapter( + WGPURequestAdapterStatus status, + WGPUAdapter adapter, + char const* message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (status != WGPURequestAdapterStatus_Success || !adapter) { + MaybeCallOnUnrecoverableError(); + return; + } + + adapter_ = wgpu::Adapter(adapter); + + // TODO(bialpio): Determine the limits based on the incoming video frames. + wgpu::RequiredLimits limits = { + .limits = {}, + }; + + auto* device_lost_callback = gpu::webgpu::BindWGPUOnceCallback( + [](base::WeakPtr<VideoEffectsProcessorWebGpu> processor, + WGPUDeviceLostReason reason, char const* message) { + if (processor) { + processor->OnDeviceLost(reason, message); + } + }, + weak_ptr_factory_.GetWeakPtr()); + wgpu::DeviceDescriptor descriptor = { + .label = "VideoEffectsProcessor", + .requiredLimits = &limits, + .defaultQueue = + { + .label = "VideoEffectsProcessorDefaultQueue", + }, + .deviceLostCallback = device_lost_callback->UnboundCallback(), + .deviceLostUserdata = device_lost_callback->AsUserdata(), + }; + + auto* request_device_callback = gpu::webgpu::BindWGPUOnceCallback( + [](base::WeakPtr<VideoEffectsProcessorWebGpu> processor, + WGPURequestDeviceStatus status, WGPUDevice device, + char const* message) { + if (processor) { + processor->OnRequestDevice(status, device, message); + } + }, + weak_ptr_factory_.GetWeakPtr()); + adapter_.RequestDevice(&descriptor, + request_device_callback->UnboundCallback(), + request_device_callback->AsUserdata()); + EnsureFlush(); +} + +void VideoEffectsProcessorWebGpu::OnRequestDevice( + WGPURequestDeviceStatus status, + WGPUDevice device, + char const* message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (status != WGPURequestDeviceStatus_Success || !device) { + MaybeCallOnUnrecoverableError(); + return; + } + + device_ = wgpu::Device(device); + device_.SetUncapturedErrorCallback(&ErrorCallback, nullptr); + device_.SetLoggingCallback(&LoggingCallback, nullptr); +} + +void VideoEffectsProcessorWebGpu::OnDeviceLost(WGPUDeviceLostReason reason, + char const* message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + device_ = {}; + + MaybeCallOnUnrecoverableError(); +} + +void VideoEffectsProcessorWebGpu::EnsureFlush() { + if (context_provider_->WebGPUInterface()->EnsureAwaitingFlush()) { + context_provider_->WebGPUInterface()->FlushAwaitingCommands(); + } +} + +void VideoEffectsProcessorWebGpu::MaybeCallOnUnrecoverableError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (on_unrecoverable_error_) { + std::move(on_unrecoverable_error_).Run(); + } +} + +// static +void VideoEffectsProcessorWebGpu::ErrorCallback(WGPUErrorType type, + char const* message, + void* userdata) { + LOG(ERROR) << "VideoEffectsProcessor encountered a WebGPU error. type: " + << type << ", message: " << (message ? message : "(unavailable)"); +} + +// static +void VideoEffectsProcessorWebGpu::LoggingCallback(WGPULoggingType type, + char const* message, + void* userdata) { + auto log_line = base::StringPrintf( + "VideoEffectsProcessor received WebGPU log message. message: %s", + (message ? message : "(unavailable)")); + + switch (type) { + case WGPULoggingType_Verbose: + [[fallthrough]]; + case WGPULoggingType_Info: + VLOG(1) << log_line; + break; + case WGPULoggingType_Warning: + LOG(WARNING) << log_line; + break; + case WGPULoggingType_Error: + LOG(ERROR) << log_line; + break; + default: + VLOG(1) << log_line; + break; + } +} + +} // namespace video_effects
diff --git a/services/video_effects/video_effects_processor_webgpu.h b/services/video_effects/video_effects_processor_webgpu.h new file mode 100644 index 0000000..2964cae --- /dev/null +++ b/services/video_effects/video_effects_processor_webgpu.h
@@ -0,0 +1,83 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_PROCESSOR_WEBGPU_H_ +#define SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_PROCESSOR_WEBGPU_H_ + +#include "base/functional/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "third_party/dawn/include/dawn/webgpu.h" +#include "third_party/dawn/include/dawn/webgpu_cpp.h" + +namespace viz { +class ContextProviderCommandBuffer; +} + +namespace video_effects { + +// Companion to `VideoEffectsProcessorImpl`. Initializes the WebGPU API that'll +// subsequently be used for post-processing the incoming video frames. +class VideoEffectsProcessorWebGpu { + public: + // `on_unrecoverable_error` will be called when this instance encounters an + // error it's unable to recover from. It is guaranteed that the callback will + // not be called synchronously from the ctor and from `Initialize()` method. + explicit VideoEffectsProcessorWebGpu( + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider, + base::OnceClosure on_unrecoverable_error); + ~VideoEffectsProcessorWebGpu(); + + VideoEffectsProcessorWebGpu(const VideoEffectsProcessorWebGpu& other) = + delete; + VideoEffectsProcessorWebGpu& operator=( + const VideoEffectsProcessorWebGpu& other) = delete; + + // Returns `true` if the synchronous part of initialization has completed. + // This does not mean that the processor is fully initialized - WebGPU + // initialization may still proceed asynchronously. + bool Initialize(); + + private: + // Ensures that awaiting WebGPUInterface commands are flushed. + void EnsureFlush(); + + // Calls `on_unrecoverable_error_` if it's set. + void MaybeCallOnUnrecoverableError(); + + void OnRequestAdapter(WGPURequestAdapterStatus status, + WGPUAdapter adapter, + char const* message); + + void OnRequestDevice(WGPURequestDeviceStatus status, + WGPUDevice device, + char const* message); + + void OnDeviceLost(WGPUDeviceLostReason reason, char const* message); + + static void ErrorCallback(WGPUErrorType type, + char const* message, + void* userdata); + + static void LoggingCallback(WGPULoggingType type, + char const* message, + void* userdata); + + scoped_refptr<viz::ContextProviderCommandBuffer> context_provider_; + + base::OnceClosure on_unrecoverable_error_; + + wgpu::Instance instance_; + wgpu::Adapter adapter_; + wgpu::Device device_; + + SEQUENCE_CHECKER(sequence_checker_); + + // Must be last: + base::WeakPtrFactory<VideoEffectsProcessorWebGpu> weak_ptr_factory_{this}; +}; + +} // namespace video_effects + +#endif // SERVICES_VIDEO_EFFECTS_VIDEO_EFFECTS_PROCESSOR_WEBGPU_H_
diff --git a/services/webnn/coreml/graph_builder.cc b/services/webnn/coreml/graph_builder.cc index e46ef139..ea6919b 100644 --- a/services/webnn/coreml/graph_builder.cc +++ b/services/webnn/coreml/graph_builder.cc
@@ -122,6 +122,15 @@ constexpr char kOpLogicalGreaterEqual[] = "greater_equal"; constexpr char kOpLogicalLess[] = "less"; constexpr char kOpLogicalLessEqual[] = "less_equal"; +constexpr char kOpCeilTypeName[] = "ceil"; +constexpr char kOpCosTypeName[] = "cos"; +constexpr char kOpExpTypeName[] = "exp"; +constexpr char kOpFloorTypeName[] = "floor"; +constexpr char kOpSinTypeName[] = "sin"; +constexpr char kOpTanTypeName[] = "tan"; +constexpr char kOpErfTypeName[] = "erf"; +constexpr char kOpSqrtTypeName[] = "sqrt"; + // Pooling operators. constexpr char kOpAvgPoolTypeName[] = "avg_pool"; constexpr char kOpL2PoolTypeName[] = "l2_pool"; @@ -1202,15 +1211,41 @@ switch (operation.kind) { case mojom::ElementWiseUnary::Kind::kCast: { const OperandInfo& input = GetOperandInfo(operation.input_operand_id); - RETURN_IF_ERROR(AddOperationForCast(input.coreml_name, - operation.output_operand_id, - input.data_type, block)); - break; + return AddOperationForCast(input.coreml_name, operation.output_operand_id, + input.data_type, block); } - default: + case mojom::ElementWiseUnary::Kind::kCeil: { + return AddUnaryFloatsOperation(kOpCeilTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kCos: { + return AddUnaryFloatsOperation(kOpCosTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kExp: { + return AddUnaryFloatsOperation(kOpExpTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kFloor: { + return AddUnaryFloatsOperation(kOpFloorTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kSin: { + return AddUnaryFloatsOperation(kOpSinTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kTan: { + return AddUnaryFloatsOperation(kOpTanTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kErf: { + return AddUnaryFloatsOperation(kOpErfTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kSqrt: { + return AddUnaryFloatsOperation(kOpSqrtTypeName, operation, block); + } + case mojom::ElementWiseUnary::Kind::kReciprocal: + case mojom::ElementWiseUnary::Kind::kLog: + case mojom::ElementWiseUnary::Kind::kNeg: + case mojom::ElementWiseUnary::Kind::kAbs: + case mojom::ElementWiseUnary::Kind::kIdentity: + case mojom::ElementWiseUnary::Kind::kLogicalNot: return NewNotSupportedError("Unimplemented Unary Operator."); } - return base::ok(); } base::expected<void, mojom::ErrorPtr> GraphBuilder::AddOperationForLeakyRelu(
diff --git a/services/webnn/tflite/graph_builder.cc b/services/webnn/tflite/graph_builder.cc index 569d05d..88f1c47 100644 --- a/services/webnn/tflite/graph_builder.cc +++ b/services/webnn/tflite/graph_builder.cc
@@ -342,6 +342,9 @@ case mojom::Operation::Tag::kLeakyRelu: operator_offset = SerializeLeakyRelu(*op.get_leaky_relu()); break; + case mojom::Operation::Tag::kMatmul: + operator_offset = SerializeMatmul(*op.get_matmul()); + break; case mojom::Operation::Tag::kPad: { ASSIGN_OR_RETURN(operator_offset, SerializePad(*op.get_pad())); break; @@ -409,8 +412,6 @@ return base::unexpected("lstm is not implemented"); case mojom::Operation::Tag::kLstmCell: return base::unexpected("lstmCell is not implemented"); - case mojom::Operation::Tag::kMatmul: - return base::unexpected("matmul is not implemented"); case mojom::Operation::Tag::kPrelu: return base::unexpected("prelu is not implemented"); case mojom::Operation::Tag::kSoftplus: @@ -1170,6 +1171,24 @@ /*output_tensor_type=*/::tflite::TensorType_UINT8); } +auto GraphBuilder::SerializeMatmul(const mojom::Matmul& matmul) + -> OperatorOffset { + const auto matmul_options = + ::tflite::CreateBatchMatMulOptions(builder_, /*adj_x=*/false, + /*adj_y=*/false); + const uint32_t operator_code_index = + GetOperatorCodeIndex(::tflite::BuiltinOperator_BATCH_MATMUL); + const std::array<int32_t, 2> op_inputs = { + operand_to_index_map_.at(matmul.a_operand_id), + operand_to_index_map_.at(matmul.b_operand_id)}; + const std::array<int32_t, 1> op_outputs = { + operand_to_index_map_.at(matmul.output_operand_id)}; + return ::tflite::CreateOperator( + builder_, operator_code_index, builder_.CreateVector<int32_t>(op_inputs), + builder_.CreateVector<int32_t>(op_outputs), + ::tflite::BuiltinOptions_BatchMatMulOptions, matmul_options.Union()); +} + auto GraphBuilder::SerializePad(const mojom::Pad& pad) -> base::expected<OperatorOffset, std::string> { CHECK_EQ(pad.beginning_padding.size(), pad.ending_padding.size());
diff --git a/services/webnn/tflite/graph_builder.h b/services/webnn/tflite/graph_builder.h index b68ae4a2..689b754 100644 --- a/services/webnn/tflite/graph_builder.h +++ b/services/webnn/tflite/graph_builder.h
@@ -167,6 +167,7 @@ OperatorOffset SerializeLeakyRelu(const mojom::LeakyRelu& leaky_relu); OperatorOffset SerializeLogicalNot( const mojom::ElementWiseUnary& logical_not); + OperatorOffset SerializeMatmul(const mojom::Matmul& matmul); base::expected<OperatorOffset, std::string> SerializePad( const mojom::Pad& pad); base::expected<OperatorOffset, std::string> SerializePool2d(
diff --git a/services/webnn/tflite/op_resolver.cc b/services/webnn/tflite/op_resolver.cc index 2f093a1..0bf88629 100644 --- a/services/webnn/tflite/op_resolver.cc +++ b/services/webnn/tflite/op_resolver.cc
@@ -28,6 +28,10 @@ ::tflite::ops::builtin::Register_ARG_MIN(), /* min_version = */ 1, /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_BATCH_MATMUL, + ::tflite::ops::builtin::Register_BATCH_MATMUL(), + /* min_version = */ 1, + /* max_version = */ 4); AddBuiltin(::tflite::BuiltinOperator_CONCATENATION, ::tflite::ops::builtin::Register_CONCATENATION(), /* min_version = */ 1,
diff --git a/services/webnn/webnn_context_impl.cc b/services/webnn/webnn_context_impl.cc index 700a194..68110345 100644 --- a/services/webnn/webnn_context_impl.cc +++ b/services/webnn/webnn_context_impl.cc
@@ -48,9 +48,12 @@ mojo::PendingAssociatedReceiver<mojom::WebNNBuffer> receiver, mojom::BufferInfoPtr buffer_info, const base::UnguessableToken& buffer_handle) { + // The token is validated in mojo traits to be non-empty. + CHECK(!buffer_handle.is_empty()); + // It is illegal to create the same buffer twice, a buffer is uniquely // identified by its UnguessableToken. - if (IsWebNNBufferValid(buffer_handle)) { + if (buffer_impls_.contains(buffer_handle)) { receiver_.ReportBadMessage(kBadMessageInvalidBuffer); return; } @@ -68,14 +71,6 @@ buffer_impls_.emplace(std::move(buffer_impl)); } -bool WebNNContextImpl::IsWebNNBufferValid( - const base::UnguessableToken& handle) const { - if (handle.is_empty()) { - return false; - } - return buffer_impls_.contains(handle); -} - void WebNNContextImpl::DisconnectAndDestroyWebNNBufferImpl( const base::UnguessableToken& handle) { const auto it = buffer_impls_.find(handle);
diff --git a/services/webnn/webnn_context_impl.h b/services/webnn/webnn_context_impl.h index 2f13caf4..4729fa5 100644 --- a/services/webnn/webnn_context_impl.h +++ b/services/webnn/webnn_context_impl.h
@@ -110,10 +110,6 @@ buffer_impls_; private: - // Determines if a WebNNBuffer is still connected with this context so WebNN - // operations can use it. - bool IsWebNNBufferValid(const base::UnguessableToken& handle) const; - // GraphsImpls which are stored on the context to allow graph // operations to use this context safely via a raw_ptr. mojo::UniqueAssociatedReceiverSet<mojom::WebNNGraph> graph_impls_;
diff --git a/services/webnn/webnn_graph_impl_backend_test.cc b/services/webnn/webnn_graph_impl_backend_test.cc index f3b7ed7..80fd23d 100644 --- a/services/webnn/webnn_graph_impl_backend_test.cc +++ b/services/webnn/webnn_graph_impl_backend_test.cc
@@ -348,6 +348,7 @@ "BuildAndComputeSingleOperatorConcat", "BuildAndComputeConcatWithConstants", "BuildAndComputeSingleOperatorElementWiseBinary", + "BuildAndComputeSingleOperatorElementWiseUnary", "BuildAndComputeSingleOperatorAveragePool2d", "BuildAndComputeSingleOperatorL2Pool2d", "BuildAndComputeSingleOperatorMaxPool2d", @@ -2770,7 +2771,7 @@ // TODO(https://crbug.com/326356909): Enable these tests when using TFLite, // after adding support for other unary operators. -#if !BUILDFLAG(WEBNN_USE_TFLITE) +#if !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<uint8_t>{ .input = {.type = mojom::Operand::DataType::kUint8, @@ -2824,7 +2825,7 @@ .output = test_operand_info_uint8} .Test(*this); } -#endif // !BUILDFLAG(WEBNN_USE_TFLITE) +#endif // !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) { // Test Sqrt with 0-D scalar input. @@ -2852,7 +2853,7 @@ // TODO(https://crbug.com/326356909): Enable these tests when using TFLite, // after adding support for float16 and other unary operators. -#if !BUILDFLAG(WEBNN_USE_TFLITE) +#if !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float16>{ .input = {.type = mojom::Operand::DataType::kFloat16, @@ -2864,6 +2865,8 @@ .values = Float16FromFloat32({0, 2, 5, 4, 8, 7})}} .Test(*this); } +#endif // !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) +#if !BUILDFLAG(WEBNN_USE_TFLITE) { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2875,6 +2878,8 @@ .values = {0, 1, 0, 1, 1, -1}}} .Test(*this); } +#endif // !BUILDFLAG(WEBNN_USE_TFLITE) +#if !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float16>{ .input = {.type = mojom::Operand::DataType::kFloat16, @@ -2911,8 +2916,8 @@ std::numeric_limits<float>::infinity()})}} .Test(*this); } -#endif // !BUILDFLAG(WEBNN_USE_TFLITE) - +#endif // !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) +#if !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2924,6 +2929,7 @@ .values = {1, 4, 2, 16, 64, 0}}} .Test(*this); } +#endif // !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2960,7 +2966,7 @@ // TODO(https://crbug.com/326356909): Enable these tests when using TFLite, // after adding support for other unary operators. -#if !BUILDFLAG(WEBNN_USE_TFLITE) +#if !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float16>{ .input = {.type = mojom::Operand::DataType::kFloat16, @@ -2972,8 +2978,8 @@ .values = Float16FromFloat32({-2, 0, 1, -3, 0, 2})}} .Test(*this); } -#endif // !BUILDFLAG(WEBNN_USE_TFLITE) - +#endif // !BUILDFLAG(WEBNN_USE_TFLITE) && !BUILDFLAG(IS_MAC) +#if !BUILDFLAG(IS_MAC) { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2996,6 +3002,7 @@ .values = {1, 0, -1.1, 2.2, 0, -2}}} .Test(*this); } +#endif { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32,
diff --git a/skia/ext/SkMemory_new_handler.cpp b/skia/ext/SkMemory_new_handler.cpp index 1bb17d47..ba23c95 100644 --- a/skia/ext/SkMemory_new_handler.cpp +++ b/skia/ext/SkMemory_new_handler.cpp
@@ -72,7 +72,7 @@ // our allocators, which should placate UBSAN. size_t old_size = sk_malloc_size(addr, 0); void* result = sk_malloc_throw(size); - memcpy(result, addr, std::min(size, old_size)); + sk_careful_memcpy(result, addr, std::min(size, old_size)); sk_free(addr); return result; #else
diff --git a/storage/browser/blob/blob_reader_unittest.cc b/storage/browser/blob/blob_reader_unittest.cc index bf1e284..c1765ae 100644 --- a/storage/browser/blob/blob_reader_unittest.cc +++ b/storage/browser/blob/blob_reader_unittest.cc
@@ -14,6 +14,7 @@ #include <utility> #include <vector> +#include "base/containers/heap_array.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -884,15 +885,15 @@ current_value = 0; for (size_t i = 0; i < kNumItems; i++) { uint64_t offset = i % 3 == 0 ? 1 : 0; - std::unique_ptr<char[]> buf(new char[kItemSize + offset]); + auto buf = base::HeapArray<char>::Uninit(kItemSize + offset); if (offset > 0) { - memset(buf.get(), 7, offset); + memset(buf.data(), 7, offset); } for (size_t j = 0; j < kItemSize; j++) { - buf.get()[j + offset] = current_value++; + buf.data()[j + offset] = current_value++; } std::unique_ptr<FakeFileStreamReader> reader(new FakeFileStreamReader( - std::string(buf.get() + offset, kItemSize), kItemSize + offset)); + std::string(buf.data() + offset, kItemSize), buf.size())); if (i % 4 != 0) { reader->SetAsyncRunner( base::SingleThreadTaskRunner::GetCurrentDefault().get());
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index bd426a1..c583109 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -24,6 +24,8 @@ #include "base/functional/callback.h" #include "base/functional/callback_forward.h" #include "base/functional/callback_helpers.h" +#include "base/functional/concurrent_callbacks.h" +#include "base/functional/concurrent_closures.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" @@ -192,37 +194,38 @@ // Gather info before computing an answer: // settings, host_usage, storage_key_quota and device_storage_capacity if // unlimited. - int callback_count = is_unlimited_ ? 3 : 2; - base::RepeatingClosure barrier = base::BarrierClosure( - callback_count, - base::BindOnce(&UsageAndQuotaInfoGatherer::OnBarrierComplete, - weak_factory_.GetWeakPtr())); - + base::ConcurrentClosures concurrent; manager()->GetQuotaSettings( base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotSettings, - weak_factory_.GetWeakPtr(), barrier)); + weak_factory_.GetWeakPtr(), concurrent.CreateClosure())); if (bucket_info_) { manager()->GetBucketUsageWithBreakdown( bucket_info_->ToBucketLocator(), base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotUsage, - weak_factory_.GetWeakPtr(), barrier)); + weak_factory_.GetWeakPtr(), + concurrent.CreateClosure())); } else { manager()->GetStorageKeyUsageWithBreakdown( storage_key_, type_, base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotUsage, - weak_factory_.GetWeakPtr(), barrier)); + weak_factory_.GetWeakPtr(), + concurrent.CreateClosure())); } // Determine storage_key_quota differently depending on type. if (is_unlimited_) { SetDesiredStorageKeyQuota(kNoLimit); - manager()->GetStorageCapacity( - base::BindOnce(&UsageAndQuotaInfoGatherer::OnGotCapacity, - weak_factory_.GetWeakPtr(), barrier)); + manager()->GetStorageCapacity(base::BindOnce( + &UsageAndQuotaInfoGatherer::OnGotCapacity, weak_factory_.GetWeakPtr(), + concurrent.CreateClosure())); } else { // For limited storage, OnGotSettings will set the host quota. } + + std::move(concurrent) + .Done(base::BindOnce(&UsageAndQuotaInfoGatherer::CallCompleted, + weak_factory_.GetWeakPtr())); } void Aborted() override { @@ -286,10 +289,10 @@ return static_cast<QuotaManagerImpl*>(observer()); } - void OnGotSettings(base::RepeatingClosure barrier_closure, + void OnGotSettings(base::OnceClosure callback, const QuotaSettings& settings) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(barrier_closure); + DCHECK(callback); settings_ = settings; const int64_t quota = @@ -298,27 +301,27 @@ SetDesiredStorageKeyQuota(quota); } - barrier_closure.Run(); + std::move(callback).Run(); } - void OnGotCapacity(base::OnceClosure barrier_closure, + void OnGotCapacity(base::OnceClosure callback, int64_t total_space, int64_t available_space) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(barrier_closure); + DCHECK(callback); DCHECK_GE(total_space, 0); DCHECK_GE(available_space, 0); total_space_ = total_space; available_space_ = available_space; - std::move(barrier_closure).Run(); + std::move(callback).Run(); } - void OnGotUsage(base::OnceClosure barrier_closure, + void OnGotUsage(base::OnceClosure callback, int64_t usage, blink::mojom::UsageBreakdownPtr usage_breakdown) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(barrier_closure); + DCHECK(callback); DCHECK_GE(usage, -1); DCHECK(usage_breakdown); DCHECK_GE(usage_breakdown->backgroundFetch, 0); @@ -330,7 +333,7 @@ usage_ = usage; usage_breakdown_ = std::move(usage_breakdown); - std::move(barrier_closure).Run(); + std::move(callback).Run(); } void SetDesiredStorageKeyQuota(int64_t quota) { @@ -340,8 +343,6 @@ desired_storage_key_quota_ = quota; } - void OnBarrierComplete() { CallCompleted(); } - // These fields are passed at construction time. const StorageKey storage_key_; // Non-null iff usage info is to be gathered for an individual bucket. If @@ -551,49 +552,39 @@ run_called_ = true; #endif // DCHECK_IS_ON() - size_t client_call_count = 0; - for (const auto& client_and_type : manager_->client_types_) { - client_call_count += client_and_type.second.size(); - } - - // Registered clients can be empty in tests. - if (!client_call_count) { - Completed(); - return; - } - - base::RepeatingClosure barrier = base::BarrierClosure( - client_call_count, - base::BindOnce(&QuotaManagerImpl::StorageKeyGathererTask::Completed, - weak_factory_.GetWeakPtr())); - - GetStorageKeysForType(StorageType::kTemporary, barrier); - GetStorageKeysForType(StorageType::kSyncable, barrier); + base::ConcurrentClosures concurrent; + GetStorageKeysForType(StorageType::kTemporary, concurrent); + GetStorageKeysForType(StorageType::kSyncable, concurrent); + std::move(concurrent) + .Done( + base::BindOnce(&QuotaManagerImpl::StorageKeyGathererTask::Completed, + weak_factory_.GetWeakPtr())); } private: - void GetStorageKeysForType(StorageType type, base::RepeatingClosure barrier) { + void GetStorageKeysForType(StorageType type, + base::ConcurrentClosures& concurrent) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto client_map_it = manager_->client_types_.find(type); DCHECK(client_map_it != manager_->client_types_.end()); - DCHECK(barrier); for (const auto& client_and_type : client_map_it->second) { client_and_type.first->GetStorageKeysForType( type, base::BindOnce(&StorageKeyGathererTask::DidGetStorageKeys, - weak_factory_.GetWeakPtr(), type, barrier)); + weak_factory_.GetWeakPtr(), type, + concurrent.CreateClosure())); } } void DidGetStorageKeys(StorageType type, - base::OnceClosure barrier, + base::OnceClosure callback, const std::vector<StorageKey>& storage_keys) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(barrier); + DCHECK(callback); storage_keys_by_type_[type].insert(storage_keys.begin(), storage_keys.end()); - std::move(barrier).Run(); + std::move(callback).Run(); } void Completed() { @@ -918,22 +909,18 @@ protected: void Run() override { DCHECK(manager()->client_types_.contains(type_)); - base::RepeatingClosure barrier = base::BarrierClosure( - manager()->client_types_[type_].size(), - base::BindOnce(&StorageCleanupHelper::CallCompleted, - weak_factory_.GetWeakPtr())); - // This may synchronously trigger |callback_| at the end of the for loop, - // make sure we do nothing after this block. + base::ConcurrentClosures concurrent; for (const auto& client_and_type : manager()->client_types_[type_]) { mojom::QuotaClient* client = client_and_type.first; QuotaClientType client_type = client_and_type.second; if (quota_client_types_.contains(client_type)) { - client->PerformStorageCleanup(type_, barrier); - } else { - barrier.Run(); + client->PerformStorageCleanup(type_, concurrent.CreateClosure()); } } + std::move(concurrent) + .Done(base::BindOnce(&StorageCleanupHelper::CallCompleted, + weak_factory_.GetWeakPtr())); } void Aborted() override { @@ -1367,10 +1354,10 @@ base::OnceCallback<void(QuotaErrorOr<int64_t>)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // This barrier is run once with each space restriction --- the StorageKey - // usage/quota and the bucket's usage/quota (if it exists). The final value is - // the more restrictive of the two. - auto barrier_aggregator = base::BindOnce( + // ConcurrentCallbacks is run once with each space restriction --- the + // StorageKey usage/quota and the bucket's usage/quota (if it exists). The + // final value is the more restrictive of the two. + auto aggregator = base::BindOnce( [](base::OnceCallback<void(QuotaErrorOr<int64_t>)> final_space_remaining, std::vector<int64_t> space_checks) { int64_t space_left = @@ -1383,13 +1370,11 @@ } }, std::move(callback)); - auto barrier = base::BarrierCallback<int64_t>( - /*num_callbacks=*/bucket.is_default ? 1 : 2, - std::move(barrier_aggregator)); + base::ConcurrentCallbacks<int64_t> concurrent; - // Translates a UsageAndQuota result into a single number for the barrier. - auto on_got_usage = base::BindRepeating( - [](base::RepeatingCallback<void(int64_t)> report_space_remaining, + // Translates a UsageAndQuota result into a single number for the aggregator. + auto on_got_usage = + [](base::OnceCallback<void(int64_t)> report_space_remaining, blink::mojom::QuotaStatusCode code, int64_t usage, int64_t quota) { // Report the amount of allocated space remaining, or min() for an // error, or max() if there's no limit. @@ -1402,17 +1387,19 @@ leftover_space = quota - usage; } std::move(report_space_remaining).Run(leftover_space); - }, - barrier); + }; // Check the usage for the whole StorageKey. - GetUsageAndQuota(bucket.storage_key, bucket.type, on_got_usage); + GetUsageAndQuota(bucket.storage_key, bucket.type, + base::BindOnce(on_got_usage, concurrent.CreateCallback())); // If this is the default bucket, we're done. Otherwise, additionally check // the usage of the specific bucket against its quota. if (!bucket.is_default) { - GetBucketUsageAndQuota(bucket.id, on_got_usage); + GetBucketUsageAndQuota( + bucket.id, base::BindOnce(on_got_usage, concurrent.CreateCallback())); } + std::move(concurrent).Done(std::move(aggregator)); } void QuotaManagerImpl::OnClientWriteFailed(const StorageKey& storage_key) { @@ -2092,9 +2079,7 @@ BucketTableEntries entries) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - base::RepeatingCallback<void(mojom::BucketTableEntryPtr)> barrier = - base::BarrierCallback<mojom::BucketTableEntryPtr>(entries.size(), - std::move(callback)); + base::ConcurrentCallbacks<mojom::BucketTableEntryPtr> concurrent; for (auto& entry : entries) { StorageType type = static_cast<StorageType>(entry->type); @@ -2120,20 +2105,22 @@ GetBucketUsageWithBreakdown( bucket_locator, base::BindOnce(&QuotaManagerImpl::AddBucketTableEntry, - weak_factory_.GetWeakPtr(), std::move(entry), barrier)); + weak_factory_.GetWeakPtr(), std::move(entry), + concurrent.CreateCallback())); } + std::move(concurrent).Done(std::move(callback)); } void QuotaManagerImpl::AddBucketTableEntry( mojom::BucketTableEntryPtr entry, - base::OnceCallback<void(mojom::BucketTableEntryPtr)> barrier_callback, + base::OnceCallback<void(mojom::BucketTableEntryPtr)> callback, int64_t usage, blink::mojom::UsageBreakdownPtr bucket_usage_breakdown) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); entry->usage = usage; - std::move(barrier_callback).Run(std::move(entry)); + std::move(callback).Run(std::move(entry)); } void QuotaManagerImpl::OnDbError(int error_code) { @@ -3043,12 +3030,9 @@ base::BarrierClosure(buckets_to_delete.size(), base::BindOnce(std::move(callback), kept_buckets)); for (const BucketInfo& bucket : buckets_to_delete) { - auto on_delete_done = base::BindOnce( - [](base::RepeatingClosure barrier, - QuotaErrorOr<mojom::BucketTableEntryPtr>) { barrier.Run(); }, - barrier); - DeleteBucketDataInternal(bucket.ToBucketLocator(), AllQuotaClientTypes(), - std::move(on_delete_done)); + DeleteBucketDataInternal( + bucket.ToBucketLocator(), AllQuotaClientTypes(), + base::IgnoreArgs<QuotaErrorOr<mojom::BucketTableEntryPtr>>(barrier)); } }
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index a7ffb07..73f158e 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -2758,7 +2758,6 @@ "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" }, { - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -4258,8 +4257,8 @@ "gtest_tests": [ { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter", - "--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome" + "--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome", + "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter" ], "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromeos.preuprev.json b/testing/buildbot/chromeos.preuprev.json index c7072fd..f19d2825 100644 --- a/testing/buildbot/chromeos.preuprev.json +++ b/testing/buildbot/chromeos.preuprev.json
@@ -336,7 +336,6 @@ "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" }, { - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" },
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index cb29321e..b128883 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1748,7 +1748,6 @@ "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" }, { - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -3244,7 +3243,6 @@ "test_id_prefix": "ninja://ash:ash_pixeltests/" }, { - "ci_only": true, "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -3434,8 +3432,8 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter", - "--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome" + "--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome", + "--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter" ], "isolate_profile_data": true, "merge": { @@ -5484,9 +5482,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5496,8 +5494,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -5514,9 +5512,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5526,8 +5524,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -5640,9 +5638,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5652,8 +5650,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -5670,9 +5668,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5682,8 +5680,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index b5473a1..60af06d 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -15538,7 +15538,6 @@ "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" }, { - "ci_only": true, "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19664,9 +19663,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19676,8 +19675,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -19694,9 +19693,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19706,8 +19705,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -19820,9 +19819,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19832,8 +19831,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -19850,9 +19849,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -19862,8 +19861,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index b8cacd7..9aff4af 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -4115,6 +4115,56 @@ { "args": [ "--test-launcher-bot-mode", + "--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter", + "--platform", + "iPhone 14", + "--version", + "17.4", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "15e204a", + "--xctest" + ], + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "content_browsertests iPhone 14 17.4", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:b28cf90d462a7bbd45c28f2d931960c2b9404cb0" + } + ], + "dimensions": { + "cpu": "arm64", + "os": "Mac-13|Mac-14" + }, + "named_caches": [ + { + "name": "xcode_ios_15e204a", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_17_4", + "path": "Runtime-ios-17.4" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "content_browsertests", + "test_id_prefix": "ninja://content/test:content_browsertests/", + "variant_id": "iPhone 14 17.4" + }, + { + "args": [ + "--test-launcher-bot-mode", "--test-launcher-filter-file=testing/buildbot/filters/ios.content_unittests.filter", "--platform", "iPhone 14", @@ -39535,7 +39585,6 @@ "test_id_prefix": "ninja://chrome/test:ash_crosapi_tests/" }, { - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41788,9 +41837,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41799,8 +41848,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -41817,9 +41866,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41828,8 +41877,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -41938,9 +41987,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41949,8 +41998,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -41967,9 +42016,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -41978,8 +42027,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -43287,9 +43336,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43299,8 +43348,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -43317,9 +43366,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43329,8 +43378,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -43443,9 +43492,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43455,8 +43504,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -43473,9 +43522,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -43485,8 +43534,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -44768,9 +44817,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44779,8 +44828,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -44797,9 +44846,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44808,8 +44857,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -44918,9 +44967,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44929,8 +44978,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -44947,9 +44996,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -44958,8 +45007,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 2327528..61df2a8 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -2817,7 +2817,6 @@ "args": [ "--test-launcher-print-test-stdio=always" ], - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -4500,7 +4499,6 @@ "args": [ "--test-launcher-print-test-stdio=always" ], - "ci_only": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -15765,12 +15763,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15780,8 +15778,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -15798,12 +15796,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15813,8 +15811,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": { @@ -15941,12 +15939,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 126.0.6425.0", + "description": "Run with ash-chrome version 126.0.6426.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15956,8 +15954,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v126.0.6425.0", - "revision": "version:126.0.6425.0" + "location": "lacros_version_skew_tests_v126.0.6426.0", + "revision": "version:126.0.6426.0" } ], "dimensions": { @@ -15974,12 +15972,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 125.0.6411.0", + "description": "Run with ash-chrome version 125.0.6422.5", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -15989,8 +15987,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v125.0.6411.0", - "revision": "version:125.0.6411.0" + "location": "lacros_version_skew_tests_v125.0.6422.5", + "revision": "version:125.0.6422.5" } ], "dimensions": {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index b77cdbe..03aa57a 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -67,6 +67,7 @@ "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter", "//testing/buildbot/filters/code_coverage.browser_tests.filter", "//testing/buildbot/filters/fuchsia.browser_tests.filter", + "//testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter", "//testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter", "//testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter", "//testing/buildbot/filters/linux-lacros.browser_tests.filter",
diff --git a/testing/buildbot/filters/android.emulator_13.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator_13.chrome_public_test_apk.filter index 05e7a94..b72b7b07 100644 --- a/testing/buildbot/filters/android.emulator_13.chrome_public_test_apk.filter +++ b/testing/buildbot/filters/android.emulator_13.chrome_public_test_apk.filter
@@ -67,10 +67,6 @@ # crbug.com/1498168 -org.chromium.chrome.browser.webapps.WebappSplashScreenTest.testThemeColorWhenNotSpecified -# crbug.com/1498169 --org.chromium.chrome.features.start_surface.InstantStartTabSwitcherTest.testSingleAsHomepage_Landscape_TabSize --org.chromium.chrome.features.start_surface.InstantStartTabSwitcherTest.testSingleAsHomepage_Landscape_TabSize_RefactorEnabled - # crbug.com/1515446 -org.chromium.chrome.browser.webauth.Fido2CredentialRequestTest.*
diff --git a/testing/buildbot/filters/ios.content_browsertests.filter b/testing/buildbot/filters/ios.content_browsertests.filter index 85c6f94c..bd1bdc7 100644 --- a/testing/buildbot/filters/ios.content_browsertests.filter +++ b/testing/buildbot/filters/ios.content_browsertests.filter
@@ -332,3 +332,312 @@ -All/WorkerTest.WebSocketSharedWorker/1 -All/WorkerTest.WebSocketSharedWorker/2 -All/WorkerTest.WebSocketSharedWorker/3 + +# TODO(crbug.com/335331442): A timeout happens after bump the version of SDK up to 17.4. +-All/AccessibilityHitTestingBrowserTest.HitTestInPopup/ZoomFactor1 +-All/AccessibilityHitTestingBrowserTest.HitTestInPopup/ZoomFactor2 +-All/CrossOriginOpenerPolicyBrowserTest.BackNavigationCoiToNonCoiAfterCrashReproducer/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.BackNavigationCoiToNonCoiAfterCrashReproducer/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.BackNavigationCoiToNonCoiAfterCrashReproducer/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.BackNavigationCoiToNonCoiAfterCrashReproducer/RDCrashedFrame_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoCoop/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoCoop/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoCoop/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoCoop/RDCrashedFrame_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoNonCoop/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoNonCoop/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoNonCoop/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.CoopPageCrashIntoNonCoop/RDCrashedFrame_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.NavigatePopupToErrorAndCrash/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.NavigatePopupToErrorAndCrash/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.NavigatePopupToErrorAndCrash/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.NavigatePopupToErrorAndCrash/RDCrashedFrame_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.NonCoopPageCrashIntoCoop/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.NonCoopPageCrashIntoCoop/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.NonCoopPageCrashIntoCoop/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.NonCoopPageCrashIntoCoop/RDCrashedFrame_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.SpeculativeSiteInstanceAndCrossOriginIsolation/RDAllFrames_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.SpeculativeSiteInstanceAndCrossOriginIsolation/RDAllFrames_BFCacheEnabled +-All/CrossOriginOpenerPolicyBrowserTest.SpeculativeSiteInstanceAndCrossOriginIsolation/RDCrashedFrame_BFCacheDisabled +-All/CrossOriginOpenerPolicyBrowserTest.SpeculativeSiteInstanceAndCrossOriginIsolation/RDCrashedFrame_BFCacheEnabled +-All/DumpAccessibilityTreeTest.AccessibilityInputDate/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputDateDisabled/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputDateWithPopupOpenMultiple/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputMonth/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputTime/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputTimeWithPopupOpen/blink +-All/DumpAccessibilityTreeTest.AccessibilityInputWeek/blink +-All/DumpAccessibilityTreeTest.AccessibilityInteractiveControlsWithLabels/blink +-All/NavigationControllerBrowserTest.BackSameDocumentInNewWindow/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTest.BackSameDocumentInNewWindow/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTest.BackSameDocumentInNewWindow/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTest.BackSameDocumentInNewWindow/RDCrashedFrame_BFCacheEnabled +-All/NavigationControllerBrowserTest.ErrorPageNavigationWithoutNavigationRequestGetsKilled/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTest.ErrorPageNavigationWithoutNavigationRequestGetsKilled/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTest.ErrorPageNavigationWithoutNavigationRequestGetsKilled/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTest.ErrorPageNavigationWithoutNavigationRequestGetsKilled/RDCrashedFrame_BFCacheEnabled +-All/NavigationControllerBrowserTest.InitialEmptyDocumentStatusAfterCrash/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTest.InitialEmptyDocumentStatusAfterCrash/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTest.InitialEmptyDocumentStatusAfterCrash/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTest.InitialEmptyDocumentStatusAfterCrash/RDCrashedFrame_BFCacheEnabled +-All/NavigationControllerBrowserTest.ReloadSadFrameWithSubframeHistoryNavigation/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTest.ReloadSadFrameWithSubframeHistoryNavigation/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTest.ReloadSadFrameWithSubframeHistoryNavigation/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTest.ReloadSadFrameWithSubframeHistoryNavigation/RDCrashedFrame_BFCacheEnabled +-All/NavigationControllerBrowserTest.SubframeBackFromSubframeLocationReplaceAfterCrash/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTest.SubframeBackFromSubframeLocationReplaceAfterCrash/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTest.SubframeBackFromSubframeLocationReplaceAfterCrash/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTest.SubframeBackFromSubframeLocationReplaceAfterCrash/RDCrashedFrame_BFCacheEnabled +-All/NavigationControllerBrowserTestNoServer.RendererInitiatedCancellationDueToCrash/RDAllFrames_BFCacheDisabled +-All/NavigationControllerBrowserTestNoServer.RendererInitiatedCancellationDueToCrash/RDAllFrames_BFCacheEnabled +-All/NavigationControllerBrowserTestNoServer.RendererInitiatedCancellationDueToCrash/RDCrashedFrame_BFCacheDisabled +-All/NavigationControllerBrowserTestNoServer.RendererInitiatedCancellationDueToCrash/RDCrashedFrame_BFCacheEnabled +-All/RenderFrameHostManagerTest.CrashFrameReloadAndCheckProxy/0 +-All/RenderFrameHostManagerTest.CrashFrameReloadAndCheckProxy/1 +-All/RenderFrameHostManagerTest.CreateRenderViewAfterProcessKillAndClosedProxy/0 +-All/RenderFrameHostManagerTest.CreateRenderViewAfterProcessKillAndClosedProxy/1 +-All/RenderFrameHostManagerTest.ErrorPageNavigationReloadWithTerminatedProcess/0 +-All/RenderFrameHostManagerTest.ErrorPageNavigationReloadWithTerminatedProcess/1 +-All/RenderFrameHostManagerTest.NavigateBackToExistingProcessFromSadTab/0 +-All/RenderFrameHostManagerTest.NavigateBackToExistingProcessFromSadTab/1 +-All/RenderFrameHostManagerTest.NavigateCrossSiteSubframeAfterCrash/0 +-All/RenderFrameHostManagerTest.NavigateCrossSiteSubframeAfterCrash/1 +-All/RenderFrameHostManagerTest.NavigateFromRevivedRendererDebugURL/0 +-All/RenderFrameHostManagerTest.NavigateFromRevivedRendererDebugURL/1 +-All/RenderFrameHostManagerTest.ReinitializeOpenerChainAfterCrashAndReload/0 +-All/RenderFrameHostManagerTest.ReinitializeOpenerChainAfterCrashAndReload/1 +-All/RenderFrameHostManagerTest.RenderViewInitAfterNewProxyAndProcessKill/0 +-All/RenderFrameHostManagerTest.RenderViewInitAfterNewProxyAndProcessKill/1 +-All/RenderFrameHostManagerTest.RenderViewInitAfterProcessKill/0 +-All/RenderFrameHostManagerTest.RenderViewInitAfterProcessKill/1 +-All/RenderFrameHostManagerTest.RestoreFileAccessForHistoryNavigationAfterCrash/0 +-All/RenderFrameHostManagerTest.RestoreFileAccessForHistoryNavigationAfterCrash/1 +-All/RenderFrameHostManagerTest.RuntimeFeatureStateDocumentDataShouldBeRecreatedAfterCrash/0 +-All/RenderFrameHostManagerTest.RuntimeFeatureStateDocumentDataShouldBeRecreatedAfterCrash/1 +-All/RenderFrameHostManagerUnloadBrowserTest.PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes/0 +-All/RenderFrameHostManagerUnloadBrowserTest.PendingDeleteRFHProcessShutdownDoesNotRemoveSubframes/1 +-All/RenderProcessHostTest.AllowUnusedProcessToExitAfterCrash/Default +-All/RenderProcessHostTest.AllowUnusedProcessToExitAfterCrash/KeepAliveInBrowserMigration +-All/RenderProcessHostTest.KillProcessOnBadMojoMessage/Default +-All/RenderProcessHostTest.KillProcessOnBadMojoMessage/KeepAliveInBrowserMigration +-All/RenderProcessHostTest.KillProcessZerosAudioStreams/Default +-All/RenderProcessHostTest.KillProcessZerosAudioStreams/KeepAliveInBrowserMigration +-All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDAllFrames_BFCacheDisabled +-All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDAllFrames_BFCacheEnabled +-All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDCrashedFrame_BFCacheDisabled +-All/CoopRestrictPropertiesAccessBrowserTest.PostCrashNavigation/RDCrashedFrame_BFCacheEnabled +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/arraybuffer +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/form +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/string +-All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/arraybuffer +-All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/string +-All/SendBeaconBrowserTest.CrossOriginAndCORSSafelistedRedirectRequest/form +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/arraybuffer +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithIframeRemoval/blob +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/blob +-All/SendBeaconBrowserTest.MultipleRedirectsRequestWithDelayedIframeRemoval/string +-All/ServiceWorkerBrowserTestWithStoragePartitioning.StorageKeyWithHostPermissionsWithSharedWorkers/0 +-All/SitePerProcessBrowserTest.AccessWindowProxyOfCrashedFrameAfterNavigation/0 +-All/SitePerProcessBrowserTest.AccessWindowProxyOfCrashedFrameAfterNavigation/1 +-All/SitePerProcessBrowserTest.ChildFrameCrashMetrics_KilledMainFrame/0 +-All/SitePerProcessBrowserTest.ChildFrameCrashMetrics_KilledMainFrame/1 +-All/SitePerProcessBrowserTest.ChildFrameCrashMetrics_ScrolledIntoView/0 +-All/SitePerProcessBrowserTest.ChildFrameCrashMetrics_ScrolledIntoView/1 +-All/SitePerProcessBrowserTest.CommittedOriginIncompatibleWithOriginLock/0 +-All/SitePerProcessBrowserTest.CommittedOriginIncompatibleWithOriginLock/1 +-All/SitePerProcessBrowserTest.CrashSubframe/0 +-All/SitePerProcessBrowserTest.CrashSubframe/1 +-All/SitePerProcessBrowserTest.CreateChildFrameAfterKillingOpener/0 +-All/SitePerProcessBrowserTest.CreateChildFrameAfterKillingOpener/1 +-All/SitePerProcessBrowserTest.CreateChildFrameAfterKillingProcess/0 +-All/SitePerProcessBrowserTest.CreateChildFrameAfterKillingProcess/1 +-All/SitePerProcessBrowserTest.KillingRendererClearsDescendantProxies/0 +-All/SitePerProcessBrowserTest.KillingRendererClearsDescendantProxies/1 +-All/SitePerProcessBrowserTest.NavigateCrashedSubframeToSameSite/0 +-All/SitePerProcessBrowserTest.NavigateCrashedSubframeToSameSite/1 +-All/SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess/0 +-All/SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess/1 +-All/SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcessWithSubtree/0 +-All/SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcessWithSubtree/1 +-All/SitePerProcessBrowserTest.NavigatingToKilledProcessRestoresAllProxies/0 +-All/SitePerProcessBrowserTest.NavigatingToKilledProcessRestoresAllProxies/1 +-All/SitePerProcessBrowserTest.PendingRFHIsCanceledWhenItsProcessDies/0 +-All/SitePerProcessBrowserTest.PendingRFHIsCanceledWhenItsProcessDies/1 +-All/SitePerProcessBrowserTest.ProcessDiesBeforeCrossSiteNavigationCompletes/0 +-All/SitePerProcessBrowserTest.ProcessDiesBeforeCrossSiteNavigationCompletes/1 +-All/SitePerProcessBrowserTest.RemoteToLocalNavigationInCrashedSubframe/0 +-All/SitePerProcessBrowserTest.RemoteToLocalNavigationInCrashedSubframe/1 +-All/SitePerProcessBrowserTest.RemoveFocusFromKilledFrame/0 +-All/SitePerProcessBrowserTest.RemoveFocusFromKilledFrame/1 +-All/SitePerProcessBrowserTest.RenderViewHostIsNotReusedAfterDelayedUnloadACK/0 +-All/SitePerProcessBrowserTest.RenderViewHostIsNotReusedAfterDelayedUnloadACK/1 +-All/SitePerProcessBrowserTest.RenderViewHostKeepsSwappedOutStateIfPendingRFHDies/0 +-All/SitePerProcessBrowserTest.RenderViewHostKeepsSwappedOutStateIfPendingRFHDies/1 +-All/SitePerProcessBrowserTest.RenderViewHostStaysActiveWithLateUnloadACK/0 +-All/SitePerProcessBrowserTest.RenderViewHostStaysActiveWithLateUnloadACK/1 +-All/SitePerProcessBrowserTest.ReuseNonLiveRenderViewHostAfterCancelPending/0 +-All/SitePerProcessBrowserTest.ReuseNonLiveRenderViewHostAfterCancelPending/1 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.CrashedSubframeVisibilityMetricsDuringParentLoad/0 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.CrashedSubframeVisibilityMetricsDuringParentLoad/1 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.CrashedSubframeVisibilityMetricsDuringTabReload/0 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.CrashedSubframeVisibilityMetricsDuringTabReload/1 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.DoNotReloadHiddenTabWithHiddenCrashedSubframe/0 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.DoNotReloadHiddenTabWithHiddenCrashedSubframe/1 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.DoNotReloadVisibleTabWithCrashedSubframe/0 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.DoNotReloadVisibleTabWithCrashedSubframe/1 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.ReloadHiddenTabWithCrashedSubframeInViewport/0 +-All/SitePerProcessBrowserTestWithSadFrameTabReload.ReloadHiddenTabWithCrashedSubframeInViewport/1 +-All/SitePerProcessBrowserTestWithoutSadFrameTabReload.ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown/0 +-All/SitePerProcessBrowserTestWithoutSadFrameTabReload.ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown/1 +-All/YieldingParserDumpAccessibilityTreeTest.AccessibilityInputDateWithPopupOpenMultiple/blink +-All/YieldingParserDumpAccessibilityTreeTest.AccessibilityInputTimeWithPopupOpen/blink +-AttributionInternalsWebUiBrowserTest.ClearButton_ClearsSourceTable +-AttributionInternalsWebUiBrowserTest.WebUIShownWithActiveImpression_ImpressionsDisplayed +-BackForwardCacheBrowserTest.BackNavigationFromCrashedPage +-BackForwardCacheBrowserTest.EvictsFromCacheIfRendererProcessCrashes +-BackForwardCacheBrowserTestWithJavaScriptDetails.StickyFeaturesWithDetails +-BrowserChildProcessObserverBrowserTest.LaunchAndCrash +-BrowserChildProcessObserverBrowserTest.LaunchAndDisconnect +-BrowserChildProcessObserverBrowserTest.LaunchAndForceShutdown +-CaptureStreamRenderProcessHostTest.KillProcessZerosAudioCaptureStreams +-CaptureStreamRenderProcessHostTest.KillProcessZerosVideoCaptureStreams +-ChildProcessSecurityPolicyInProcessBrowserTest.NoLeak +-CommitNavigationRaceBrowserTest.CrashedInPendingCommit/NavigationQueueing +-CommitNavigationRaceBrowserTest.CrashedInPendingCommit/UndoCommitNavigation +-CrossPlatformAccessibilityBrowserTest.ControlsIdsForColorPopup +-CrossPlatformAccessibilityBrowserTest.ControlsIdsForDateTimePopup +-CrossSiteTransferTest.MaliciousPostWithFileData +-DataDecoderBrowserTest.NoCallbackAfterDestruction_Gzip +-DataDecoderBrowserTest.NoCallbackAfterDestruction_Json +-DataDecoderBrowserTest.NoCallbackAfterDestruction_Xml +-DatabaseTest.ModificationsPersistAfterRendererCrash +-DevToolsProtocolDeviceEmulationTest.RenderKillDoesNotCrashBrowser +-DevToolsProtocolTest.CrossSiteCrash +-DevToolsProtocolTest.DoubleCrash +-DevToolsProtocolTest.InspectorTargetCrashedNavigate +-DevToolsProtocolTest.InspectorTargetCrashedNavigateCrossProcess +-DevToolsProtocolTest.InspectorTargetCrashedReload +-DevToolsProtocolTest.PageCrashClearsPendingCommands +-DevToolsProtocolTest.ResponseAfterReload +-DevToolsProtocolTest.TargetGetTargetsAfterCrash +-DocumentUserDataTest.CheckWithFrameCrashBeforeNavigation +-DocumentUserDataTest.CheckWithFrameCrashDuringNavigation +-DocumentUserDataTest.CheckWithRenderFrameCreationAfterRendererDebugURLCrash +-DocumentUserDataTest.CrashedFrameUserDataIsPreservedAndDeletedOnReset +-FencedFrameSecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenParamsOnFencedFrameNav +-FileChooserImplBrowserTest.FileChooserAfterRfhDeath +-FileChooserImplBrowserTest.FileChooserCallbackAfterRfhDeathCancel +-FileChooserImplBrowserTest.FileChooserCallbackAfterRfhDeathSelected +-FindRequestManagerTest.CrashDuringFind +-FrameTreeBrowserTest.FrameTreeAfterCrash +-IndexedDBBrowserTest.DoesntHangTest +-IndexedDBBrowserTest.NegativeDBDataVersion +-IndexedDBBrowserTest.NegativeDBSchemaVersion +-IndexedDBBrowserTestWithCorruption.OperationOnCorruptedOpenDatabase/0 +-InterestGroupBiddingAndAuctionServerBrowserTest.ChecksPermissionPolicyWarning +-InterestGroupBiddingAndAuctionServerBrowserTest.TestEmpty +-IsolatedOriginTest.LocalStorageOriginEnforcement_IsolatedAccessingNonIsolated +-IsolatedOriginTest.LocalStorageOriginEnforcement_OpaqueOrigin +-IsolatedOriginTest.LocalStorage_EmptyLocalFrameToken +-IsolatedOriginTest.LocalStorage_WrongLocalFrameToken +-IsolatedOriginTest.SessionStorage_EmptyLocalFrameToken +-IsolatedOriginTest.SessionStorage_WrongLocalFrameToken +-IsolatedOriginTest.SessionStorage_WrongOrigin +-LoaderBrowserTest.DynamicTitle1 +-LoaderBrowserTest.DynamicTitle2 +-MessagePortCloseEventBrowserTest.CloseEventHappensIfProcessCrashes +-MediaSessionPictureInPictureContentBrowserTest.ActionAvailableAfterEndOfStreamAndSrcUpdate +-MediaSessionServiceImplBrowserTest.ResetServiceWhenNavigatingAway +-NavigationBrowserTest.PostUploadIllegalFilePath +-NavigationBrowserTest.ProcessShutdownDuringDeferredNavigationThrottle +-NavigationCookiesBrowserTest.CookiesInheritedSrcDoc +-NavigationRequestBrowserTest.CancelNavigationInWillStartRequest +-NavigationRequestBrowserTest.EarlySwapMetrics_CrashNoCommit +-NavigationRequestBrowserTest.EarlySwapMetrics_CrashedSubframe +-NavigationRequestBrowserTest.NoLeakFromStartingSiteInstance +-NavigationRequestBrowserTest.RendererCrashedBeforeCommitErrorPage +-NetworkServiceBrowserTest.WebUIBindingsNoHttp +-NetworkServiceNetLogBrowserTest.LogCreated +-PageImplTest.NewPageObjectCreatedOnFrameCrash +-PageImplTest.SameSiteNavigationAfterFrameCrash +-PointerLockBrowserTest.PointerLockInnerContentsCrashes +-PointerLockBrowserTest.PointerLockOopifCrashes +-PolicyContainerHostBrowserTest.CheckRendererPolicyContainerAccessesAfterCrash +-PrerenderBrowserTest.AbandonIfPrimaryMainFrameRendererProcessIsKilled +-PrerenderBrowserTest.AbandonIfRendererProcessCrashes +-PrerenderBrowserTest.AbandonIfRendererProcessIsKilled +-RenderFrameDevToolsAgentHostFencedFrameBrowserTest.PageCrashInFencedFrame +-RenderFrameHostImplBrowserTest.CheckRFHLifecycleStateWhenRendererCrashes +-RenderFrameHostImplBrowserTest.DevToolsNavigationToken_EarlyCommitAfterCrash +-RenderFrameHostImplBrowserTest.FileReloadAfterCrash +-RenderFrameHostImplBrowserTest.GetCanonicalUrlAfterRendererCrash +-RenderFrameHostImplBrowserTest.NotifiesProcessHostOfAudibleAudio +-RenderFrameHostImplBrowserTest.RequestSnapshotAXTreeAfterRenderProcessHostDeath +-RenderFrameHostImplBrowserTest.TerminationDisablersClearedOnRendererCrash +-RenderFrameHostImplBrowserTest.WebUiReloadAfterCrash +-RenderAccessibilityImplTest.TestHitTestPopupDoesNotCrash +-RenderFrameDevToolsAgentHostBrowserTest.CancelCrossOriginNavigationAfterReadyToCommit +-RenderWidgetHostDelegatedInkMetadataTest.FlagGetsSetFromRenderFrameMetadata +-SandboxedHttpCacheBrowserTest.CreateSimpleCacheOnParentDirectory +-SandboxedHttpCacheBrowserTest.CreateSimpleCacheWithParentDirectoryTraversal +-SecurityExploitBrowserTest.BadUrlSchemeOnCommit +-SecurityExploitBrowserTest.BadUrlSchemeOnSameDocumentCommit +-SecurityExploitBrowserTest.BindToWebUIFromWebViaMojo +-SecurityExploitBrowserTest.CrossOriginSameDocumentCommit +-SecurityExploitBrowserTest.CrossOriginSameDocumentCommitFromAboutBlank +-SecurityExploitBrowserTest.CrossOriginSameDocumentCommitUniversalAccessNonFile +-SecurityExploitBrowserTest.DidCommitInvalidURL +-SecurityExploitBrowserTest.DidCommitInvalidURLWithOpaqueOrigin +-SecurityExploitBrowserTest.InvalidBeginNavigationInitiator +-SecurityExploitBrowserTest.InvalidRemoteNavigationInitiator +-SecurityExploitBrowserTest.MismatchedOriginOnCommit +-SecurityExploitBrowserTest.MismatchedOriginOnDocumentOpenURLUpdate +-SecurityExploitBrowserTest.MissingBeginNavigationInitiator +-SecurityExploitBrowserTest.MissingInterfaceProviderOnNonSameDocumentCommit +-SecurityExploitBrowserTest.NonInitialAboutBlankRendererKill +-SecurityExploitBrowserTest.NonWebbyTransition +-SecurityExploitBrowserTest.OpenUrl_ResourceRequestBody +-SecurityExploitBrowserTest.PostMessageSourceOrigin +-SecurityExploitBrowserTest.SetWebUIProperty +-SecurityExploitBrowserTest.UnfencedTopFromOutsideFencedFrame +-SecurityExploitBrowserTest.WebUIProcessDidCommitWebURL +-SecurityExploitBrowserTestFencedFrames.ChangeFencedFrameSandboxFlags +-SecurityExploitBrowserTestFencedFrames.NavigateFencedFrameToInvalidURL +-SecurityExploitBrowserTestFencedFrames.PullFocusAcrossFencedBoundary +-SecurityExploitBrowserTestMojoBlobURLs/SecurityExploitBrowserTestMojoBlobURLsP.CreateMojoBlobURLInDifferentOrigin/0 +-SecurityExploitBrowserTestMojoBlobURLs/SecurityExploitBrowserTestMojoBlobURLsP.CreateMojoBlobURLInDifferentOrigin/1 +-SecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenIssuanceWithoutPermissionsPolicy +-SecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenParamsOnMainFrameNav +-SecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenRedemptionWithoutPermissionsPolicy +-SecurityExploitBrowserTestWithTrustTokensEnabled.BrowserForbidsTrustTokenSigningWithoutPermissionsPolicy +-SecurityExploitTestFencedFramesDisabled.CreateFencedFrameWhenFeatureDisabled +-SecurityExploitViaDisabledWebSecurityTest.FullscreenRequestMustBeFromEmptyDocument +-SecurityExploitViaDisabledWebSecurityTest.ValidateBaseUrlForDataUrl +-ServiceProcessHostBrowserTest.AllMessagesReceived +-ServiceProcessHostBrowserTest.IdleTimeout +-ServiceProcessHostBrowserTest.LocalDisconnectQuits +-ServiceProcessHostBrowserTest.ObserveCrash +-ServiceProcessHostBrowserTest.RemoteDisconnectQuits +-ServiceWorkerVersionBrowserTest.RendererCrash +-SitePerProcessDevToolsProtocolTest.PageCrashInFrame +-SitePerProcessHitTestBrowserTest.CancelWheelScrollBubblingOnWheelTargetDeletion +-SitePerProcessHitTestBrowserTest.LargeCursorRemovedInScrolledOOPIF +-SnapshotBrowserTest.AsyncMultiWindowTest +-SnapshotBrowserTest.SyncMultiWindowTest +-SpareRenderProcessHostManagerTest.SpareRenderProcessHostKilled +-TrustTokenBrowsertest.SigningRequiresRedemptionRecordInStorage +-UtilityProcessHostBrowserTest.LaunchProcessAndCrash +-ViewTransitionBrowserTest.NavigationCancelledBeforeScreenshot +-ViewTransitionBrowserTest.NavigationCancelledAfterScreenshot +-ViewTransitionBrowserTest.OwnershipTransferredToNewRenderer +-WebContentsImplBrowserTest.DeferredWindowOpenNavigationIsResumedWithEarlySwap +-WebContentsImplBrowserTest.FocusFromJavaScriptEndsFullscreen +-WebContentsImplBrowserTest.MediaDestroyedOnRendererCrash +-WebContentsImplBrowserTest.PopupsFromJavaScriptDoNotEndFullscreenWithinTab +-WebContentsImplBrowserTest.PopupsFromJavaScriptEndFullscreen +-WebContentsImplBrowserTest.PopupsFromJavaScriptEndFullscreenDownstream +-WebContentsImplBrowserTest.PopupsOfPopupsFromJavaScriptEndFullscreen +-WebContentsImplBrowserTest.ReinitializeMainFrameForCrashedTab +-WebUIImplBrowserTest.NavigateFromCrashedAboutBlank +-WebContentsObserverBrowserTest.CookieCallbacks_Subframe +-WebContentsObserverBrowserTest.CookieCallbacks_Subresource
diff --git a/testing/buildbot/filters/ios.use_blink.components_unittests.filter b/testing/buildbot/filters/ios.use_blink.components_unittests.filter index b2837ad..b41a8949 100644 --- a/testing/buildbot/filters/ios.use_blink.components_unittests.filter +++ b/testing/buildbot/filters/ios.use_blink.components_unittests.filter
@@ -91,16 +91,46 @@ -FormMutationFormControlElements.RemovedFormControlElement/7 -FormMutationFormControlElements.RemovedFormControlElement/8 -FormMutationFormControlElements.RemovedFormControlElement/9 + +# TODO(crbug.com/335686693): FormMutationTests have been failing since +# https://crrev.com/c/5460162. Currently they fail with use_blink due to +# spinning up on an unexpected thread. -FormMutationTest.AddForm/0 -FormMutationTest.AddForm/1 --FormMutationTest.FormRemovalRegistered/0 --FormMutationTest.FormRemovalRegistered/1 +-FormMutationTest.AddForm/2 +-FormMutationTest.AddForm/3 +-FormMutationTest.PasswordFormRemovalRegistered/0 +-FormMutationTest.PasswordFormRemovalRegistered/1 +-FormMutationTest.PasswordFormRemovalRegistered/2 +-FormMutationTest.PasswordFormRemovalRegistered/3 +-FormMutationTest.RemoveFormlessFields/0 +-FormMutationTest.RemoveFormlessFields/1 +-FormMutationTest.RemoveFormlessFields/2 +-FormMutationTest.RemoveFormlessFields/3 -FormMutationTest.RemoveFormlessPasswordFields/0 -FormMutationTest.RemoveFormlessPasswordFields/1 +-FormMutationTest.RemoveFormlessPasswordFields/2 +-FormMutationTest.RemoveFormlessPasswordFields/3 +-FormMutationTest.RemoveMultipleForms/0 +-FormMutationTest.RemoveMultipleForms/1 +-FormMutationTest.RemoveMultipleForms/2 +-FormMutationTest.RemoveMultipleForms/3 +-FormMutationTest.RemoveMultipleFormsAndFormlessFields/0 +-FormMutationTest.RemoveMultipleFormsAndFormlessFields/1 +-FormMutationTest.RemoveMultipleFormsAndFormlessFields/2 +-FormMutationTest.RemoveMultipleFormsAndFormlessFields/3 +-FormMutationTest.RemoveNonPasswordForm/0 +-FormMutationTest.RemoveNonPasswordForm/1 +-FormMutationTest.RemoveNonPasswordForm/2 +-FormMutationTest.RemoveNonPasswordForm/3 -FormMutationTest.RemovedAndAddedFormsRegistered/0 -FormMutationTest.RemovedAndAddedFormsRegistered/1 +-FormMutationTest.RemovedAndAddedFormsRegistered/2 +-FormMutationTest.RemovedAndAddedFormsRegistered/3 -FormMutationTest.RemovedAndAddedFormsRegistered_WithDroppedMessages/0 -FormMutationTest.RemovedAndAddedFormsRegistered_WithDroppedMessages/1 +-FormMutationTest.RemovedAndAddedFormsRegistered_WithDroppedMessages/2 +-FormMutationTest.RemovedAndAddedFormsRegistered_WithDroppedMessages/3 # TODO(crbug.com/1505328): Test currently fails on iOS blink. -FormJsTest.GetIframeElements
diff --git a/testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter b/testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter new file mode 100644 index 0000000..bf1d26b --- /dev/null +++ b/testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter
@@ -0,0 +1,97 @@ +# A list of disabled tests for browser_tests_require_lacros +# on linux-chromeos-chrome-with-lacros builder. + +*Magn*.* +AccessibilityExtension* +AccessibilityHighlightsBrowserTest.* +AppServiceAppWindowLacrosBrowserTest* +Autoclick* +AshTtsApiTest* +BrowserAppShelfControllerBrowserTest* +ChromeAppKioskLacrosTest* +ChromeVox* +DemoAshRequiresLacrosTest* +DesksTemplatesClientLacrosTest* +Dictation* +*DictationTest* +EduCoexistenceWithArcRestrictionsMochaTest* +ExtensionKeeplistAllowPerfettoTest* +ExtensionKeeplistTest* +# Note: Some of FileTasksBrowserTest* runs only on branded ash and lacros builds. +*FileTasksBrowserTest* +NonKioskAcceleratorLacrosTest* +*OSSettingsMochaTestLacrosAndRevampEnabled* +*OSSettingsMochaTestLacrosEnabledRevampDisabled* +SelectToSpeak* +StickyKeysBrowserTest* +SwitchAccess* +VpnExtensionObserverBrowserTest* +WebAppsCrosapiBrowserTest* +*WebAppsPreventCloseCrosapiBrowserTest* +WebAppInstallerLacrosBrowserTest* +WebAppProviderBridgeBrowserTest* +WebKioskAcceleratorLacrosTest* +WebKioskLacrosTest* +CrosapiSystemLogSourceTest* +TaskManagerAshBrowserTest* +TestAsNormalAndGuestUser/SpokenFeedbackTest.* +# TODO(b/262789941) Enable more accessibility tests. +# TODO(b/260289935): Flaky in Lacros. +-ChromeVoxBackgroundTest.TabSwitchAndRefreshRecovery +-ChromeVoxPortalsTest.PortalName +-ChromeVoxPortalsTest.ShouldFocusPortal +# TODO(b/276914335): Flaky in Lacros. +-ChromeVoxAutoScrollHandlerTest.RecyclerViewByCharacter +# TODO(b/301475127): Remove browser() dependency for the following dictation +# tests. +-*DictationTest.Help* +-*DictationTest.WorksWithSelectToSpeak* +# TODO(b/301253962): Some Switch Access tests fail/flake on Lacros. +-SwitchAccessItemScanManagerTest.* +-SwitchAccessPointScanManagerTest.PointScanLeftClick +-SwitchAccessTest.NavigateButtonsInTextFieldMenu +# TODO(https://crbug.com/1378291) Ash and Lacros browser window sizes differ. +-ChromeVoxEditingTest.SelectAcrossSoftLineWraps +# TODO(b/277821091) Flaky +-ChromeVoxEditingTest.GiantTextAreaPerformance +# TODO(crbug.com/1478586): Flaky. +-AutoclickWithAccessibilityServiceTest.ScrollableBoundsPlumbing +# TODO(b/277256412): Test is flaky +-DictationUIE2ETest.HintsTimeoutWithChromeVox +# TODO(b/316393493): Figure out how to set home button pref in Lacros. +-StickyKeysBrowserTest.CtrlClickHomeButton +# TODO(accessibility): these are native C++ tests that need investigation. +-TestAsNormalAndGuestUser/SpokenFeedbackTest.NavigateChromeVoxMenu* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.ShowFormControlsList* +-SelectToSpeakTest.ContinuesReadingDuringResize +# TODO(b/318357300): Flaky. +-AccessibilityHighlightsBrowserTest.CaretHighlightOmnibox +# These tests do not run with the browser and do not need to run with Lacros. +-AccessibilityCommonTest* +-AccessibilityPrivateApiTest* +-MagnificationManagerTest* +-FullscreenMagnifierControllerTest.MovesContinuouslyWithMouse +-FullscreenMagnifierControllerTest.MovesWithMouseAtEdge +-FullscreenMagnifierControllerTest.ChangeZoomWithAccelerator +-FullscreenMagnifierControllerTest.ChangeZoomWithPrefs +-AccessibilityHighlightsBrowserTest.CursorHighlightAddsFocusRing +-SelectToSpeakTest.SelectToSpeakDoesNotDismissTrayBubble +-SelectToSpeakTest.SpeakStatusTray +-StickyKeysBrowserTest.OpenTrayMenu +-StickyKeysBrowserTest.OverlayShown +-LoggedInSpokenFeedbackTest.OpenLogPage* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.TouchExploreStatusTray* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.ShelfBlockedAppIconBadgeAnnouncement* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.ShelfNotificationBadgeAnnouncement* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.ShelfPausedAppIconBadgeAnnouncement* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.SpeakingTextUnderMouseForShelfItem* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.FocusShelf* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.ShelfIconFocusForward* +-TestAsNormalAndGuestUser/SpokenFeedbackTest.TouchExploreSecondaryDisplay* +-TouchExplorationTest +-SelectToSpeakMouseSelectionTest.VoiceSwitching +# TODO(crbug.com/330377625): Permanently failing, no culprit identified. +-ChromeVoxSettingsPagesTest.TtsRateCommandOnSettingsPage +# TODO(crbug.com/330450836): Permanently failing, no culprit identified. +-AccessibilityHighlightsBrowserTest.CaretHighlightWebContents +-AccessibilityHighlightsBrowserTest.FocusHighlight
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index db68bdfc..5e7d566 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1219,9 +1219,17 @@ }, 'browser_tests_require_lacros': { 'modifications': { + 'linux-chromeos-chrome-with-lacros': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.branded.browser_tests.require_lacros.filter' + ] + }, 'linux-chromeos-rel': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter' + ], 'retry_only_failed_tests': True - } + }, } }, 'capture_unittests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 2f2279e..07178d3 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -4140,6 +4140,12 @@ '--test-launcher-filter-file=testing/buildbot/filters/ios.compositor_unittests.filter', ], }, + 'content_browsertests': { + 'args': [ + '--test-launcher-bot-mode', + '--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter', + ], + }, 'content_unittests': { 'args': [ '--test-launcher-bot-mode', @@ -4419,7 +4425,6 @@ 'browser_tests_require_lacros': { 'test': 'browser_tests', 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter', '--lacros-chrome-path=lacros_clang_x64/test_lacros_chrome', ], 'swarming': { @@ -4451,7 +4456,6 @@ 'ci_only': True, }, 'ash_unittests': { - 'ci_only': True, 'swarming': { 'shards': 5, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 87b049c..a1e33cc 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -267,32 +267,32 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'identifier': 'Lacros version skew testing ash canary', - 'description': 'Run with ash-chrome version 126.0.6425.0', + 'description': 'Run with ash-chrome version 126.0.6426.0', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6425.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v126.0.6426.0/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v126.0.6425.0', - 'revision': 'version:126.0.6425.0', + 'location': 'lacros_version_skew_tests_v126.0.6426.0', + 'revision': 'version:126.0.6426.0', }, ], }, }, 'LACROS_VERSION_SKEW_DEV': { 'identifier': 'Lacros version skew testing ash dev', - 'description': 'Run with ash-chrome version 125.0.6411.0', + 'description': 'Run with ash-chrome version 125.0.6422.5', 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6411.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v125.0.6422.5/test_ash_chrome', ], 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v125.0.6411.0', - 'revision': 'version:125.0.6411.0', + 'location': 'lacros_version_skew_tests_v125.0.6422.5', + 'revision': 'version:125.0.6422.5', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 187d5ed..3c66b16f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -379,24 +379,6 @@ ] } ], - "AndroidHub": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "floating_action_button": "false" - }, - "enable_features": [ - "AndroidHub" - ] - } - ] - } - ], "AndroidLowLatencyCanvas": [ { "platforms": [ @@ -719,21 +701,6 @@ ] } ], - "AppsCollectionsFeature": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "AppsCollections" - ] - } - ] - } - ], "ArcIgnoreHoverEventAnr": [ { "platforms": [ @@ -3779,21 +3746,6 @@ ] } ], - "ChromeOSOobeQuickStart": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "OobeQuickStart" - ] - } - ] - } - ], "ChromeOSPrintingIppUsb": [ { "platforms": [ @@ -9954,16 +9906,19 @@ ], "experiments": [ { - "name": "enabled_proxy_a_ip_protection_phase_02_16_2024", + "name": "enabled_proxy_a_ip_protection_phase_04_18_2024", "params": { "IpPrivacyAuthTokenCacheBatchSize": "1", "IpPrivacyAuthTokenCacheLowWaterMark": "1", - "IpPrivacyDirectOnly": "true", + "IpPrivacyBsaEnablePrivacyPass": "true", + "IpPrivacyDirectOnly": "false", + "IpPrivacyIncludeOAuthTokenInGetProxyConfig": "true", "IpPrivacyTokenServer": "https://phosphor-pa.googleapis.com", - "IpPrivacyTokenServerGetInitialDataPath": "/v1/ipblinding/darklaunch/getInitialData", + "IpPrivacyTokenServerGetInitialDataPath": "/v1/ipblinding/getInitialData", "IpPrivacyTokenServerGetProxyConfigPath": "/v1/ipblinding/getProxyConfig", - "IpPrivacyTokenServerGetTokensPath": "/v1/ipblinding/darklaunch/auth", - "MaskedDomainListExperimentalVersion": "3c" + "IpPrivacyTokenServerGetTokensPath": "/v1/ipblinding/auth", + "IpPrivacyUseProxyChains": "true", + "MaskedDomainListExperimentalVersion": "rc0" }, "enable_features": [ "EnableIpPrivacyProxy", @@ -18992,21 +18947,6 @@ ] } ], - "TabSateFlatBuffer": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled_20240408", - "enable_features": [ - "TabStateFlatBuffer" - ] - } - ] - } - ], "TabSearchFuzzySearchStudy": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index 51c5800..cc77051 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 51c580031adcab9ab6c5c719fd92b9ba4e591ef5 +Subproject commit cc770518b07ce9ef45cd1c283e9f69b3711d304e
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index d2d8817..085f165 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -321,29 +321,6 @@ "BiddingAndScoringDebugReportingAPI", base::FEATURE_ENABLED_BY_DEFAULT); -// Blink garbage collection. -// Enables compaction of backing stores on Blink's heap. -BASE_FEATURE(kBlinkHeapCompaction, - "BlinkHeapCompaction", - base::FEATURE_ENABLED_BY_DEFAULT); -// Enables concurrently marking Blink's heap. -BASE_FEATURE(kBlinkHeapConcurrentMarking, - "BlinkHeapConcurrentMarking", - base::FEATURE_ENABLED_BY_DEFAULT); -// Enables concurrently sweeping Blink's heap. -BASE_FEATURE(kBlinkHeapConcurrentSweeping, - "BlinkHeapConcurrentSweeping", - base::FEATURE_ENABLED_BY_DEFAULT); -// Enables incrementally marking Blink's heap. -BASE_FEATURE(kBlinkHeapIncrementalMarking, - "BlinkHeapIncrementalMarking", - base::FEATURE_ENABLED_BY_DEFAULT); -// Enables a marking stress mode that schedules more garbage collections and -// also adds additional verification passes. -BASE_FEATURE(kBlinkHeapIncrementalMarkingStress, - "BlinkHeapIncrementalMarkingStress", - base::FEATURE_DISABLED_BY_DEFAULT); - // Enable intervention for download that was initiated from or occurred in an ad // frame without user activation. BASE_FEATURE(kBlockingDownloadsInAdFrameWithoutUserActivation, @@ -1338,6 +1315,16 @@ &kLCPCriticalPathPredictor, "lcpp_enable_image_load_priority_for_htmlimageelement", false}; +const base::FeatureParam<int> kLCPCriticalPathPredictorMaxHostsToTrack{ + &kLCPCriticalPathPredictor, "lcpp_max_hosts_to_track", 100}; + +const base::FeatureParam<int> + kLCPCriticalPathPredictorHistogramSlidingWindowSize{ + &kLCPCriticalPathPredictor, "lcpp_histogram_sliding_window_size", 1000}; + +const base::FeatureParam<int> kLCPCriticalPathPredictorMaxHistogramBuckets{ + &kLCPCriticalPathPredictor, "lcpp_max_histogram_buckets", 10}; + BASE_FEATURE(kLCPScriptObserver, "LCPScriptObserver", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/common/interest_group/auction_config_mojom_traits.cc b/third_party/blink/common/interest_group/auction_config_mojom_traits.cc index fb6d6bb7..b6a8b65f 100644 --- a/third_party/blink/common/interest_group/auction_config_mojom_traits.cc +++ b/third_party/blink/common/interest_group/auction_config_mojom_traits.cc
@@ -385,12 +385,21 @@ return false; } - // `decision_logic_url` and, if present, `trusted_scoring_signals_url` must - // share the seller's origin, and must be HTTPS. Need to explicitly check the - // scheme because some non-HTTPS URLs may have HTTPS origins (e.g., blob - // URLs). Trusted signals URLs also have additional restrictions (no query, - // etc). - if ((out->decision_logic_url && + // If present and valid, `decision_logic_url` and + // `trusted_scoring_signals_url` must share the seller's origin, and must be + // HTTPS. Need to explicitly check the scheme because some non-HTTPS URLs may + // have HTTPS origins (e.g., blob URLs). Trusted signals URLs also have + // additional restrictions (no query, etc). + // + // Invalid GURLs are allowed through because even though the renderer code + // doesn't let invalid GURLs through, trying to pass a too-long GURL through + // Mojo results in an invalid GURL on the other side. Rather than preventing + // that from happening through, GURL consumers generally just let such GURLs + // flow to the network stack, where they return network errors, so we copy + // that behavior with auctions. Even when one component of an auction has + // invalid GURLs due to this, other components may not, and it's possible + // there's a winner. + if ((out->decision_logic_url && out->decision_logic_url->is_valid() && !out->IsHttpsAndMatchesSellerOrigin(*out->decision_logic_url)) || (out->trusted_scoring_signals_url && !out->IsValidTrustedScoringSignalsURL(
diff --git a/third_party/blink/common/interest_group/auction_config_mojom_traits_test.cc b/third_party/blink/common/interest_group/auction_config_mojom_traits_test.cc index ee6f0b8..3d64c2e 100644 --- a/third_party/blink/common/interest_group/auction_config_mojom_traits_test.cc +++ b/third_party/blink/common/interest_group/auction_config_mojom_traits_test.cc
@@ -148,6 +148,25 @@ EXPECT_FALSE(SerializeAndDeserialize(auction_config)); } +// Tests that decision logic GURLs exceeding max length can be passed through +// Mojo and will be converted into invalid, empty GURLs, and passing in invalid +// URLs works as well. +TEST(AuctionConfigMojomTraitsTest, SellerDecisionUrlTooLong) { + GURL seller_url = + GURL("https://seller.test/" + std::string(url::kMaxURLChars, '1')); + AuctionConfig auction_config = CreateBasicAuctionConfig(seller_url); + + AuctionConfig auction_config_clone; + bool success = + mojo::test::SerializeAndDeserialize<blink::mojom::AuctionAdConfig>( + auction_config, auction_config_clone); + ASSERT_TRUE(success); + EXPECT_EQ(auction_config.seller, auction_config_clone.seller); + EXPECT_EQ(GURL(), auction_config_clone.decision_logic_url); + + EXPECT_TRUE(SerializeAndDeserialize(auction_config_clone)); +} + TEST(AuctionConfigMojomTraitsTest, SellerScoringSignalsUrlMismatch) { AuctionConfig auction_config = CreateBasicAuctionConfig(GURL("http://seller.test"));
diff --git a/third_party/blink/perf_tests/css/CSSQuotesCreate.html b/third_party/blink/perf_tests/css/CSSQuotesCreate.html new file mode 100644 index 0000000..63c083e --- /dev/null +++ b/third_party/blink/perf_tests/css/CSSQuotesCreate.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<script src="../resources/runner.js"></script> +<style> + div { + quotes: "A" "Z"; + } + div::before { + content: open-quote; + } + div::after { + content: close-quote; + } +</style> +<body></body> +<script> + function createTree(root, num_elements, depth) { + if (!depth) { + return; + } + for (let i = 0; i < num_elements; ++i) { + const div = document.createElement('div'); + root.append(div); + createTree(div, num_elements, depth - 1); + } + } + + PerfTestRunner.measureTime({ + description: 'Measure the time of the css quotes creation', + run: function() { + document.body.innerHTML = ''; + createTree(document.body, 5, 6); + }, + iterationCount: 5, + }); +</script>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index b08a616..919fd6ef 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -189,12 +189,6 @@ // Debug reporting runtime flag/JS API. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBiddingAndScoringDebugReportingAPI); -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapCompaction); -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapConcurrentMarking); -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapConcurrentSweeping); -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarking); -BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarkingStress); - // If enabled, navigation IPCs are prioritized in blink. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kBlinkSchedulerPrioritizeNavigationIPCs); @@ -762,6 +756,20 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> kLCPCriticalPathPredictorImageLoadPriorityEnabledForHTMLImageElement; +// Size of LRU caches for the host data for LCP critical path predictor (LCPP). +BLINK_COMMON_EXPORT extern const base::FeatureParam<int> + kLCPCriticalPathPredictorMaxHostsToTrack; + +// The virtual sliding window size for LCP critical path predictor (LCPP) +// histogram. +BLINK_COMMON_EXPORT extern const base::FeatureParam<int> + kLCPCriticalPathPredictorHistogramSlidingWindowSize; + +// The max histogram bucket count that can be stored in the LCP critical path +// predictor (LCPP) database. +BLINK_COMMON_EXPORT extern const base::FeatureParam<int> + kLCPCriticalPathPredictorMaxHistogramBuckets; + // If enabled, script execution is observed to determine script dependencies of // the LCP element. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPScriptObserver);
diff --git a/third_party/blink/public/web/web_ax_object.h b/third_party/blink/public/web/web_ax_object.h index 5d1394ce..6585fd4 100644 --- a/third_party/blink/public/web/web_ax_object.h +++ b/third_party/blink/public/web/web_ax_object.h
@@ -193,8 +193,8 @@ WebNode GetNode() const; WebDocument GetDocument() const; - bool AccessibilityIsIgnored() const; - bool AccessibilityIsIncludedInTree() const; + bool IsIgnored() const; + bool IsIncludedInTree() const; // Get the verb associated with performing the default action // on this object.
diff --git a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc index 6ea42a5e..9bbdd08e 100644 --- a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc +++ b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
@@ -106,23 +106,14 @@ callback_this.V8Value(callback_->CallbackRelevantScriptState()); } if (auto* tracker = scheduler::TaskAttributionTracker::From(isolate)) { - // There are 3 possible callbacks here: - // a) Callbacks which track their registering task as their parent - // b) Callbacks which don't do the above, split into two groups: - // 1) If there's a current running task, no need to create a new scope. - // 2) If there is no current running task, set the parent to - // std::nullopt, making the current callback a root task. - scheduler::TaskAttributionInfo* parent_task = nullptr; + scheduler::TaskAttributionInfo* task_state_to_propagate = nullptr; if constexpr (std::is_same< CallbackBase, CallbackFunctionWithTaskAttributionBase>::value) { - parent_task = callback_->GetParentTask(); + task_state_to_propagate = callback_->GetParentTask(); } - if (parent_task || !tracker->RunningTask()) { - task_attribution_scope_ = tracker->CreateTaskScope( - callback_->CallbackRelevantScriptState(), parent_task, - scheduler::TaskAttributionTracker::TaskScopeType::kCallback); - } + task_attribution_scope_ = tracker->MaybeCreateTaskScopeForCallback( + callback_->CallbackRelevantScriptState(), task_state_to_propagate); } }
diff --git a/third_party/blink/renderer/core/accessibility/ax_object_cache.h b/third_party/blink/renderer/core/accessibility/ax_object_cache.h index d11b8304..40e056b 100644 --- a/third_party/blink/renderer/core/accessibility/ax_object_cache.h +++ b/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -239,18 +239,6 @@ virtual void MarkElementDirty(const Node*) = 0; - // Notifies that an AXObject is dirty and its state needs - // to be serialized again. If |subtree| is true, the entire subtree is - // dirty. - // |event_from| and |event_from_action| annotate this node change with info - // about the event which caused the change. For example, an event from a user - // or an event from a focus action. - virtual void AddDirtyObjectToSerializationQueue( - AXObject* obj, - ax::mojom::blink::EventFrom event_from, - ax::mojom::blink::Action event_from_action, - const std::vector<ui::AXEventIntent>& event_intents) = 0; - // Returns a vector of the images found in |updates|. virtual void GetImagesToAnnotate(ui::AXTreeUpdate& updates, std::vector<ui::AXNodeData*>&) = 0;
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.cc b/third_party/blink/renderer/core/html/forms/html_option_element.cc index 2e3e33a5..c6c0ba2 100644 --- a/third_party/blink/renderer/core/html/forms/html_option_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -403,6 +403,9 @@ } HTMLSelectListElement* HTMLOptionElement::OwnerSelectList() const { + if (!RuntimeEnabledFeatures::HTMLSelectListElementEnabled()) { + return nullptr; + } for (auto& ancestor : FlatTreeTraversal::AncestorsOf(*this)) { if (auto* selectlist = DynamicTo<HTMLSelectListElement>(ancestor)) { return selectlist;
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc index dc7059d..7ade261a 100644 --- a/third_party/blink/renderer/core/html/forms/select_type.cc +++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -452,7 +452,10 @@ } } + CHECK(option_slot_); if (RuntimeEnabledFeatures::StylableSelectEnabled()) { + CHECK(button_slot_); + CHECK(datalist_slot_); button_slot_->Assign(buttons); datalist_slot_->Assign(first_datalist); if (default_datalist_->popoverOpen()) { @@ -1576,6 +1579,7 @@ option_nodes.push_back(child); } } + CHECK(option_slot_); option_slot_->Assign(option_nodes); if (RuntimeEnabledFeatures::StylableSelectEnabled()) { select_->GetShadowRoot()->SetDelegatesFocus(false);
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.cc b/third_party/blink/renderer/core/layout/inline/line_breaker.cc index 0db1ac1..a7973c7 100644 --- a/third_party/blink/renderer/core/layout/inline/line_breaker.cc +++ b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
@@ -313,18 +313,6 @@ index_list->push_back(char_index); } -float ComputeWordWidth(const ShapeResult& shape_result, - wtf_size_t start_offset, - wtf_size_t end_offset) { - const wtf_size_t offset_adjust = shape_result.StartIndex(); - const float start_position = - shape_result.CachedPositionForOffset(start_offset - offset_adjust); - const float end_position = - shape_result.CachedPositionForOffset(end_offset - offset_adjust); - return IsLtr(shape_result.Direction()) ? end_position - start_position - : start_position - end_position; -} - inline LayoutTextCombine* MayBeTextCombine(const InlineItem* item) { if (!item) return nullptr; @@ -340,6 +328,25 @@ return max; } +// Represents data associated with an `InlineItemResult`. +class FastMinTextContext { + STACK_ALLOCATED(); + + public: + LayoutUnit HyphenInlineSize(InlineItemResult& item_result) const { + if (!hyphen_inline_size_) { + if (!item_result.hyphen) { + item_result.ShapeHyphen(); + } + hyphen_inline_size_ = item_result.hyphen.InlineSize(); + } + return *hyphen_inline_size_; + } + + private: + mutable std::optional<LayoutUnit> hyphen_inline_size_; +}; + } // namespace inline bool LineBreaker::ShouldAutoWrap(const ComputedStyle& style) const { @@ -1671,12 +1678,12 @@ DCHECK_EQ(shape_result.StartIndex(), item.StartOffset()); DCHECK_GE(start_offset, shape_result.StartIndex()); shape_result.EnsurePositionData(); + FastMinTextContext context; const String& text = Text(); const bool should_break_spaces = item.Style()->ShouldBreakSpaces(); float min_width = 0; unsigned last_end_offset = 0; unsigned end_offset = start_offset + 1; - std::optional<LayoutUnit> hyphen_inline_size; while (start_offset < item.EndOffset()) { // TODO(crbug.com/332328872): `following()` scans back to the start of the // string. Resetting the ICU `BreakIterator` is faster than the scanning. @@ -1702,12 +1709,6 @@ bool has_hyphen = text[non_hangable_run_end - 1] == kSoftHyphenCharacter; if (UNLIKELY(hyphenation_)) { // When 'hyphens: auto', compute all hyphenation opportunities. - if (!hyphen_inline_size) { - if (!item_result->hyphen) { - item_result->ShapeHyphen(); - } - hyphen_inline_size = item_result->hyphen.InlineSize(); - } const StringView word(text, start_offset, word_len); Vector<wtf_size_t, 8> locations = hyphenation_->HyphenLocations(word); // |locations| is a list of hyphenation points in the descending order. @@ -1716,12 +1717,15 @@ DCHECK(!locations.Contains(0u)); DCHECK(!locations.Contains(word_len)); locations.push_back(0); + const LayoutUnit hyphen_inline_size = + context.HyphenInlineSize(*item_result); LayoutUnit max_part_width; for (const wtf_size_t location : locations) { - LayoutUnit part_width = LayoutUnit::FromFloatCeil(ComputeWordWidth( - shape_result, start_offset + location, start_offset + word_len)); + LayoutUnit part_width = + LayoutUnit::FromFloatCeil(shape_result.CachedWidth( + start_offset + location, start_offset + word_len)); if (has_hyphen) - part_width += *hyphen_inline_size; + part_width += hyphen_inline_size; max_part_width = std::max(part_width, max_part_width); word_len = location; has_hyphen = true; @@ -1729,18 +1733,14 @@ min_width = std::max(max_part_width.ToFloat(), min_width); } else { float word_width = - ComputeWordWidth(shape_result, start_offset, non_hangable_run_end); + shape_result.CachedWidth(start_offset, non_hangable_run_end); // Append hyphen-width to `word_width` if the word is hyphenated. if (has_hyphen) { - if (!hyphen_inline_size) { - if (!item_result->hyphen) { - item_result->ShapeHyphen(); - } - hyphen_inline_size = item_result->hyphen.InlineSize(); - } + const LayoutUnit hyphen_inline_size = + context.HyphenInlineSize(*item_result); word_width = - (LayoutUnit::FromFloatCeil(word_width) + *hyphen_inline_size) + (LayoutUnit::FromFloatCeil(word_width) + hyphen_inline_size) .ToFloat(); }
diff --git a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc index 464ec967..9fdeb58 100644 --- a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc +++ b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
@@ -971,6 +971,8 @@ primary_height.ascent); result_height.descent = std::min(LayoutUnit(result_height.descent.Ceil()), primary_height.descent); + result_height.Move(line_item.rect.offset.block_offset + + primary_height.ascent); return result_height; } if (const auto& layout_result = line_item.layout_result) {
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h index c37f04c6..b85392c 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -303,8 +303,8 @@ bool is_preloaded_with_early_hints_; - HeapHashCountedSet<Member<ImageResourceObserver>> observers_; - HeapHashCountedSet<Member<ImageResourceObserver>> finished_observers_; + HeapHashCountedSet<WeakMember<ImageResourceObserver>> observers_; + HeapHashCountedSet<WeakMember<ImageResourceObserver>> finished_observers_; #if DCHECK_IS_ON() bool is_update_image_being_called_ = false;
diff --git a/third_party/blink/renderer/core/timing/build.gni b/third_party/blink/renderer/core/timing/build.gni index fcad4d4..ef212032 100644 --- a/third_party/blink/renderer/core/timing/build.gni +++ b/third_party/blink/renderer/core/timing/build.gni
@@ -80,6 +80,8 @@ "responsiveness_metrics.h", "render_blocking_metrics_reporter.cc", "render_blocking_metrics_reporter.h", + "soft_navigation_context.cc", + "soft_navigation_context.h", "soft_navigation_heuristics.cc", "soft_navigation_heuristics.h", "soft_navigation_entry.cc",
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_context.cc b/third_party/blink/renderer/core/timing/soft_navigation_context.cc new file mode 100644 index 0000000..0b2cc1f --- /dev/null +++ b/third_party/blink/renderer/core/timing/soft_navigation_context.cc
@@ -0,0 +1,15 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/timing/soft_navigation_context.h" + +namespace blink { + +SoftNavigationContext::SoftNavigationContext() = default; + +void SoftNavigationContext::SetUrl(const String& url) { + url_ = url; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_context.h b/third_party/blink/renderer/core/timing/soft_navigation_context.h new file mode 100644 index 0000000..db8964c --- /dev/null +++ b/third_party/blink/renderer/core/timing/soft_navigation_context.h
@@ -0,0 +1,51 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_SOFT_NAVIGATION_CONTEXT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_SOFT_NAVIGATION_CONTEXT_H_ + +#include "base/time/time.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +class CORE_EXPORT SoftNavigationContext + : public GarbageCollected<SoftNavigationContext> { + public: + SoftNavigationContext(); + + base::TimeTicks UserInteractionTimestamp() const { + return user_interaction_timestamp_; + } + void SetUserInteractionTimestamp(base::TimeTicks value) { + user_interaction_timestamp_ = value; + } + + const String& Url() const { return url_; } + void SetUrl(const String& url); + + void MarkURLChange() { has_url_change_ = true; } + bool HasURLChange() const { return has_url_change_; } + + void MarkMainModification() { has_main_modification_ = true; } + bool HasMainModification() const { return has_main_modification_; } + + void Trace(Visitor*) const {} + + bool IsSoftNavigation() const { + return has_main_modification_ && has_url_change_ && !url_.empty(); + } + + private: + base::TimeTicks user_interaction_timestamp_; + String url_; + bool has_url_change_ = false; + bool has_main_modification_ = false; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_SOFT_NAVIGATION_CONTEXT_H_
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc index f9979e0..1f1f89d 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/paint/timing/paint_timing.h" #include "third_party/blink/renderer/core/paint/timing/paint_timing_detector.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" +#include "third_party/blink/renderer/core/timing/soft_navigation_context.h" #include "third_party/blink/renderer/platform/scheduler/public/task_attribution_info.h" #include "third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h" @@ -49,8 +50,7 @@ void LogAndTraceDetectedSoftNavigation(LocalFrame* frame, LocalDOMWindow* window, - String url, - base::TimeTicks user_click_timestamp) { + const SoftNavigationContext& context) { CHECK(frame && frame->IsMainFrame()); CHECK(window); if (!RuntimeEnabledFeatures::SoftNavigationHeuristicsEnabled(window)) { @@ -59,14 +59,14 @@ auto* console_message = MakeGarbageCollected<ConsoleMessage>( mojom::blink::ConsoleMessageSource::kJavaScript, mojom::blink::ConsoleMessageLevel::kInfo, - String("A soft navigation has been detected: ") + url); + String("A soft navigation has been detected: ") + context.Url()); window->AddConsoleMessage(console_message); TRACE_EVENT_INSTANT("scheduler,devtools.timeline,loading", "SoftNavigationHeuristics_SoftNavigationDetected", - user_click_timestamp, "frame", - GetFrameIdForTracing(frame), "url", url, "navigationId", - window->GetNavigationId()); + context.UserInteractionTimestamp(), "frame", + GetFrameIdForTracing(frame), "url", context.Url(), + "navigationId", window->GetNavigationId()); } } // namespace @@ -137,36 +137,30 @@ } void SoftNavigationHeuristics::Dispose() { - if (has_potential_soft_navigation_task_ && - potential_soft_navigation_tasks_.empty()) { - RecordUmaForNonSoftNavigationInteractions(); + for (const auto& context : potential_soft_navigations_) { + RecordUmaForNonSoftNavigationInteraction(*context.Get()); } } -void SoftNavigationHeuristics::RecordUmaForNonSoftNavigationInteractions() - const { - for (const auto& task_id_and_interaction_data : - interaction_task_id_to_interaction_data_) { - const PerInteractionData& data = *task_id_and_interaction_data.value; - - // For all interactions which included a URL modification, log the - // criteria which were not met. Note that we assume here that an ancestor - // task was found when the URL change was made. - if (data.flag_set.Has(kURLChange)) { - if (!data.flag_set.Has(FlagType::kMainModification)) { - if (!paint_conditions_met_) { - base::UmaHistogramEnumeration( - kPageLoadInternalSoftNavigationOutcome, - SoftNavigationOutcome::kNoDomModification); - } else { - base::UmaHistogramEnumeration( - kPageLoadInternalSoftNavigationOutcome, - SoftNavigationOutcome::kNoPaintOrDomModification); - } - } else if (!paint_conditions_met_) { - base::UmaHistogramEnumeration(kPageLoadInternalSoftNavigationOutcome, - SoftNavigationOutcome::kNoPaint); +void SoftNavigationHeuristics::RecordUmaForNonSoftNavigationInteraction( + const SoftNavigationContext& context) const { + // For all interactions which included a URL modification, log the + // criteria which were not met. Note that we assume here that an ancestor + // task was found when the URL change was made. + if (context.HasURLChange()) { + if (!context.HasMainModification()) { + if (!paint_conditions_met_) { + base::UmaHistogramEnumeration( + kPageLoadInternalSoftNavigationOutcome, + SoftNavigationOutcome::kNoDomModification); + } else { + base::UmaHistogramEnumeration( + kPageLoadInternalSoftNavigationOutcome, + SoftNavigationOutcome::kNoPaintOrDomModification); } + } else if (!paint_conditions_met_) { + base::UmaHistogramEnumeration(kPageLoadInternalSoftNavigationOutcome, + SoftNavigationOutcome::kNoPaint); } } } @@ -184,178 +178,111 @@ void SoftNavigationHeuristics::ResetHeuristic() { // Reset previously seen indicators and task IDs. - has_potential_soft_navigation_task_ = false; - potential_soft_navigation_tasks_.clear(); - interaction_task_id_to_interaction_data_.clear(); - soft_navigation_interaction_data_ = nullptr; - last_interaction_task_id_ = scheduler::TaskAttributionId(); - last_soft_navigation_ancestor_task_ = std::nullopt; - soft_navigation_descendant_cache_.clear(); + potential_soft_navigations_.clear(); + last_detected_soft_navigation_ = nullptr; + active_interaction_context_ = nullptr; + uncommitted_same_document_navigation_context_ = nullptr; SetIsTrackingSoftNavigationHeuristicsOnDocument(false); - did_reset_paints_ = false; did_commit_previous_paints_ = false; - soft_navigation_conditions_met_ = false; - pending_interaction_timestamp_ = base::TimeTicks(); paint_conditions_met_ = false; softnav_painted_area_ = 0; } -void SoftNavigationHeuristics::UserInitiatedInteraction() { - // Ensure that paints would be reset, so that paint recording would continue - // despite the user interaction. - did_reset_paints_ = false; - ResetPaintsIfNeeded(); -} - -std::optional<scheduler::TaskAttributionId> -SoftNavigationHeuristics::GetUserInteractionAncestorTaskIfAny() { - if (potential_soft_navigation_tasks_.empty()) { - return std::nullopt; +SoftNavigationContext* +SoftNavigationHeuristics::GetSoftNavigationContextForCurrentTask() { + if (potential_soft_navigations_.empty()) { + return nullptr; } - if (auto* tracker = scheduler::TaskAttributionTracker::From( - GetSupplementable()->GetIsolate())) { - scheduler::TaskAttributionInfo* task = tracker->RunningTask(); - if (!task) { - return std::nullopt; - } - auto cached_result = - soft_navigation_descendant_cache_.find(task->Id().value()); - if (cached_result != soft_navigation_descendant_cache_.end()) { - return cached_result->value; - } - std::optional<scheduler::TaskAttributionId> ancestor_task_id; - if (potential_soft_navigation_tasks_.Contains(task)) { - ancestor_task_id = task->Id(); - } - soft_navigation_descendant_cache_.insert(task->Id().value(), - ancestor_task_id); - return ancestor_task_id; + auto* tracker = scheduler::TaskAttributionTracker::From( + GetSupplementable()->GetIsolate()); + // The `tracker` must exist if `potential_soft_navigations_` is non-empty. + CHECK(tracker); + auto* task_state = tracker->RunningTask(); + if (!task_state) { + return nullptr; } - return std::nullopt; -} - -std::optional<scheduler::TaskAttributionId> -SoftNavigationHeuristics::SetFlagIfDescendantAndCheck(FlagType type) { - std::optional<scheduler::TaskAttributionId> result = - GetUserInteractionAncestorTaskIfAny(); - if (!result) { - // A non-descendent URL change should not set the flag. - return std::nullopt; + SoftNavigationContext* context = + task_state ? task_state->GetSoftNavigationContext() : nullptr; + // `task_state` can have null `context` in tests. `context` can be non-null + // but not in `potential_soft_navigations_` if the heuristic was reset, e.g. + // if `context` was already considered a soft navigation. In that case, return + // null. + if (!context || !potential_soft_navigations_.Contains(context)) { + return nullptr; } - PerInteractionData* data = GetCurrentInteractionData(result.value()); - if (!data) { - return std::nullopt; - } - data->flag_set.Put(type); - CheckSoftNavigationConditions(*data); - return result; + return context; } void SoftNavigationHeuristics::SameDocumentNavigationStarted() { - last_soft_navigation_ancestor_task_ = - SetFlagIfDescendantAndCheck(FlagType::kURLChange); - if (!last_soft_navigation_ancestor_task_) { + uncommitted_same_document_navigation_context_ = + GetSoftNavigationContextForCurrentTask(); + if (uncommitted_same_document_navigation_context_) { + uncommitted_same_document_navigation_context_->MarkURLChange(); + EmitSoftNavigationEntryIfAllConditionsMet( + uncommitted_same_document_navigation_context_); + } else { base::UmaHistogramEnumeration(kPageLoadInternalSoftNavigationOutcome, SoftNavigationOutcome::kNoAncestorTask); } TRACE_EVENT1("scheduler", "SoftNavigationHeuristics::SameDocumentNavigationStarted", - "descendant", !!last_soft_navigation_ancestor_task_); + "descendant", !!uncommitted_same_document_navigation_context_); } + void SoftNavigationHeuristics::SameDocumentNavigationCommitted( const String& url) { - if (!last_soft_navigation_ancestor_task_) { - return; - } - PerInteractionData* data = - GetCurrentInteractionData(last_soft_navigation_ancestor_task_.value()); - if (!data) { + SoftNavigationContext* context = + uncommitted_same_document_navigation_context_.Get(); + uncommitted_same_document_navigation_context_ = nullptr; + if (!context) { return; } // This is overriding the URL, which is required to support history // modifications inside a popstate event. - data->url = url; - CheckSoftNavigationConditions(*data); + context->SetUrl(url); + EmitSoftNavigationEntryIfAllConditionsMet(context); TRACE_EVENT1("scheduler", "SoftNavigationHeuristics::SameDocumentNavigationCommitted", "url", url); } bool SoftNavigationHeuristics::ModifiedDOM() { - bool descendant = - SetFlagIfDescendantAndCheck(FlagType::kMainModification).has_value(); + SoftNavigationContext* context = GetSoftNavigationContextForCurrentTask(); + if (context) { + context->MarkMainModification(); + EmitSoftNavigationEntryIfAllConditionsMet(context); + } TRACE_EVENT1("scheduler", "SoftNavigationHeuristics::ModifiedDOM", - "descendant", descendant); - return descendant; -} - -void SoftNavigationHeuristics::CheckSoftNavigationConditions( - const SoftNavigationHeuristics::PerInteractionData& data) { - if (data.flag_set != FlagTypeSet::All()) { - return; - } - // The URL is empty when we saw a Same-Document navigation started, but it - // wasn't yet committed (and hence we may not know the URL just yet). - if (data.url.empty()) { - return; - } - - // Here we consider that we've detected a soft navigation. - soft_navigation_conditions_met_ = true; - soft_navigation_interaction_data_ = &data; - - EmitSoftNavigationEntryIfAllConditionsMet(GetLocalFrameIfNotDetached()); + "has_context", !!context); + return !!context; } void SoftNavigationHeuristics::EmitSoftNavigationEntryIfAllConditionsMet( - LocalFrame* frame) { + SoftNavigationContext* context) { + LocalFrame* frame = GetLocalFrameIfNotDetached(); // TODO(crbug.com/1510706): See if we need to add `paint_conditions_met_` back // into this condition. - if (!soft_navigation_conditions_met_ || !soft_navigation_interaction_data_ || - soft_navigation_interaction_data_->url.IsNull() || - soft_navigation_interaction_data_->user_interaction_timestamp.is_null() || - !frame || !frame->IsOutermostMainFrame()) { + if (!context || !context->IsSoftNavigation() || + context->UserInteractionTimestamp().is_null() || !frame || + !frame->IsOutermostMainFrame()) { return; } - LocalDOMWindow* window = frame->DomWindow(); - CHECK(window); + last_detected_soft_navigation_ = context; + + LocalDOMWindow* window = GetSupplementable(); ++soft_navigation_count_; window->GenerateNewNavigationId(); auto* performance = DOMWindowPerformance::performance(*window); - performance->AddSoftNavigationEntry( - AtomicString(soft_navigation_interaction_data_->url), - soft_navigation_interaction_data_->user_interaction_timestamp); + performance->AddSoftNavigationEntry(AtomicString(context->Url()), + context->UserInteractionTimestamp()); CommitPreviousPaints(frame); - LogAndTraceDetectedSoftNavigation( - frame, window, soft_navigation_interaction_data_->url, - soft_navigation_interaction_data_->user_interaction_timestamp); - - ReportSoftNavigationToMetrics(frame); + LogAndTraceDetectedSoftNavigation(frame, window, *context); + ReportSoftNavigationToMetrics(frame, context); ResetHeuristic(); } -SoftNavigationHeuristics::PerInteractionData* -SoftNavigationHeuristics::GetCurrentInteractionData( - scheduler::TaskAttributionId task_id) { - // Get interaction ID from task ID - auto interaction_it = task_id_to_interaction_task_id_.find(task_id.value()); - if (interaction_it != task_id_to_interaction_task_id_.end()) { - task_id = scheduler::TaskAttributionId(interaction_it->value); - } - // Get interaction data from interaction id - auto data_it = interaction_task_id_to_interaction_data_.find(task_id.value()); - if (data_it == interaction_task_id_to_interaction_data_.end()) { - // This can happen when events are triggered out of the expected order. e.g. - // when we get a keyup event without a keydown event that preceded it. That - // can happen in tests. - return nullptr; - } - - return data_it->value.Get(); -} - // This is called from Text/ImagePaintTimingDetector when a paint is recorded // there. void SoftNavigationHeuristics::RecordPaint( @@ -376,12 +303,12 @@ // We haven't seen an interaction yet, so we are still measuring initial // paint area. CHECK(!is_modified_by_soft_navigation); - CHECK(!has_potential_soft_navigation_task_); + CHECK(potential_soft_navigations_.empty()); initial_painted_area_ += painted_area; return; } - if (!has_potential_soft_navigation_task_) { + if (potential_soft_navigations_.empty()) { // We aren't measuring a soft-nav so we can just exit. return; } @@ -409,77 +336,75 @@ bool is_above_threshold = (softnav_painted_area_scaled > required_paint_area_scaled); - TRACE_EVENT_INSTANT("loading", "SoftNavigationHeuristics_RecordPaint", - "softnav_painted_area", softnav_painted_area_, - "softnav_painted_area_ratio", softnav_painted_area_ratio, - "url", - (soft_navigation_interaction_data_ - ? soft_navigation_interaction_data_->url - : ""), - "is_above_threshold", is_above_threshold); + TRACE_EVENT_INSTANT( + "loading", "SoftNavigationHeuristics_RecordPaint", "softnav_painted_area", + softnav_painted_area_, "softnav_painted_area_ratio", + softnav_painted_area_ratio, "url", + (last_detected_soft_navigation_ ? last_detected_soft_navigation_->Url() + : ""), + "is_above_threshold", is_above_threshold); + // TODO(crbug.com/1510706): GC between DOM modification and paint could cause + // `last_detected_soft_navigation_` to be cleared, preventing the entry from + // being emitted if `paint_conditions_met_` wasn't set but will be in the + // subsequent paint. This problem existed in task attribution v1 as well since + // the heuristic is reset when `potential_soft_navigations_` becomes empty. if (is_above_threshold) { paint_conditions_met_ = true; - EmitSoftNavigationEntryIfAllConditionsMet(frame); + EmitSoftNavigationEntryIfAllConditionsMet( + last_detected_soft_navigation_.Get()); } } void SoftNavigationHeuristics::SetCurrentTimeAsStartTime() { + // `active_interaction_context_` will be null if a soft navigation entry was + // emitted before the `EventScope` was destroyed. + if (!active_interaction_context_) { + return; + } // The interaction timestamp for non-"new interactions" will be be set to the - // processing-end time of the associated "new interaction" event, either via - // `pending_interaction_timestamp_` (if the "new interaction" event didn't - // have an event listener) or by resuing the `PerInteractionData` from that - // interaction. + // processing-end time of the associated "new interaction" event. // - // Note: kNavigate `EventScope`s considered new interactions even though they - // may be nested within an existing new interaction. This causes the + // Note: kNavigate `EventScope`s are considered new interactions even though + // they may be nested within an existing new interaction. This causes the // interaction timestamp to be set to the end of the navigate event // processing, which is intended. if (!CurrentEventParameters().is_new_interaction) { return; } - if (!last_interaction_task_id_.value()) { - pending_interaction_timestamp_ = base::TimeTicks::Now(); - return; - } - PerInteractionData* data = - GetCurrentInteractionData(last_interaction_task_id_); - CHECK(data); - if (data->user_interaction_timestamp.is_null()) { + if (active_interaction_context_->UserInteractionTimestamp().is_null()) { // Only set the timestamp if it wasn't previously set, otherwise in the case // of nested `EventScope`s (e.g. navigate event within a click event) the // the timestamp set at the end of the navigate event processing would be // overwritten. - data->user_interaction_timestamp = base::TimeTicks::Now(); + active_interaction_context_->SetUserInteractionTimestamp( + base::TimeTicks::Now()); } - LocalFrame* frame = GetLocalFrameIfNotDetached(); - EmitSoftNavigationEntryIfAllConditionsMet(frame); + EmitSoftNavigationEntryIfAllConditionsMet(active_interaction_context_.Get()); } void SoftNavigationHeuristics::ReportSoftNavigationToMetrics( - LocalFrame* frame) const { + LocalFrame* frame, + SoftNavigationContext* context) const { auto* loader = frame->Loader().GetDocumentLoader(); if (!loader) { return; } - CHECK( - !soft_navigation_interaction_data_->user_interaction_timestamp.is_null()); + CHECK(!context->UserInteractionTimestamp().is_null()); auto soft_navigation_start_time = loader->GetTiming().MonotonicTimeToPseudoWallTime( - soft_navigation_interaction_data_->user_interaction_timestamp); + context->UserInteractionTimestamp()); if (soft_navigation_start_time.is_zero()) { internal:: RecordUmaForPageLoadInternalSoftNavigationFromReferenceInvalidTiming( - soft_navigation_interaction_data_->user_interaction_timestamp, + context->UserInteractionTimestamp(), loader->GetTiming().ReferenceMonotonicTime()); } - LocalDOMWindow* window = frame->DomWindow(); - - CHECK(window); + LocalDOMWindow* window = GetSupplementable(); blink::SoftNavigationMetrics metrics = {soft_navigation_count_, soft_navigation_start_time, @@ -500,35 +425,29 @@ if (!frame || !frame->IsOutermostMainFrame()) { return; } - if (!did_reset_paints_) { - LocalFrameView* local_frame_view = frame->View(); - CHECK(local_frame_view); - LocalDOMWindow* window = GetSupplementable(); - if (RuntimeEnabledFeatures::SoftNavigationHeuristicsEnabled(window)) { - if (Document* document = window->document(); - document && - RuntimeEnabledFeatures::SoftNavigationHeuristicsExposeFPAndFCPEnabled( - window)) { - PaintTiming::From(*document).ResetFirstPaintAndFCP(); - } - local_frame_view->GetPaintTimingDetector().RestartRecordingLCP(); + LocalFrameView* local_frame_view = frame->View(); + CHECK(local_frame_view); + LocalDOMWindow* window = GetSupplementable(); + if (RuntimeEnabledFeatures::SoftNavigationHeuristicsEnabled(window)) { + if (Document* document = window->document(); + document && + RuntimeEnabledFeatures::SoftNavigationHeuristicsExposeFPAndFCPEnabled( + window)) { + PaintTiming::From(*document).ResetFirstPaintAndFCP(); } - - local_frame_view->GetPaintTimingDetector().RestartRecordingLCPToUkm(); - - did_reset_paints_ = true; + local_frame_view->GetPaintTimingDetector().RestartRecordingLCP(); } + + local_frame_view->GetPaintTimingDetector().RestartRecordingLCPToUkm(); } // Once all the soft navigation conditions are met (verified in -// CheckSoftNavigationConditions), the previous paints are committed, to make -// sure accumulated FP, FCP and LCP entries are properly fired. +// `EmitSoftNavigationEntryIfAllConditionsMet()`), the previous paints are +// committed, to make sure accumulated FP, FCP and LCP entries are properly +// fired. void SoftNavigationHeuristics::CommitPreviousPaints(LocalFrame* frame) { - if (!frame || !frame->IsOutermostMainFrame()) { - return; - } - LocalDOMWindow* window = frame->DomWindow(); - CHECK(window); + CHECK(frame && frame->IsOutermostMainFrame()); + LocalDOMWindow* window = GetSupplementable(); if (!did_commit_previous_paints_) { LocalFrameView* local_frame_view = frame->View(); @@ -546,9 +465,9 @@ void SoftNavigationHeuristics::Trace(Visitor* visitor) const { Supplement<LocalDOMWindow>::Trace(visitor); - visitor->Trace(potential_soft_navigation_tasks_); - visitor->Trace(interaction_task_id_to_interaction_data_); - visitor->Trace(soft_navigation_interaction_data_); + visitor->Trace(last_detected_soft_navigation_); + visitor->Trace(active_interaction_context_); + visitor->Trace(uncommitted_same_document_navigation_context_); // Register a custom weak callback, which runs after processing weakness for // the container. This allows us to observe the collection becoming empty // without needing to observe individual element disposal. @@ -558,52 +477,41 @@ } void SoftNavigationHeuristics::OnCreateTaskScope( - scheduler::TaskAttributionInfo& task) { + scheduler::TaskAttributionInfo& task_state) { + CHECK(active_interaction_context_); + // A task scope can be created without a `SoftNavigationContext` or one that + // differs from the one associated with the current `EventScope` if, for + // example, a previously created and awaited promise is resolved in an event + // handler. + if (task_state.GetSoftNavigationContext() != + active_interaction_context_.Get()) { + return; + } + + // TODO(crbug.com/40942324): Replace task_id with either an id for the + // `SoftNavigationContext` or a serialized version of the object. TRACE_EVENT1("scheduler", "SoftNavigationHeuristics::OnCreateTaskScope", - "task_id", task.Id().value()); + "task_id", task_state.Id().value()); // This is invoked when executing a callback with an active `EventScope`, // which happens for click and keyboard input events, as well as - // user-initiated navigation and popstate events. Any such events should be - // considered a potential soft navigation root tasks. - potential_soft_navigation_tasks_.insert(&task); - has_potential_soft_navigation_task_ = true; - - const EventParameters& current_event_parameters = CurrentEventParameters(); - // If `last_interaction_task_id_` isn't set, then no event listeners for any - // associated events have run yet -- either in the intital "new interaction" - // `EventScope`, a nested `EventScope`, or a subsequent non-"new interaction" - // (e.g. keyup) `EventScope`. In that case, no `PerInteractionData` data has - // been created for the current interaction, so create one now that the - // interaction is a potential soft navigation. - // - // Note: multiple event listeners might within an `EventScope`, but the - // `last_interaction_task_id_` will only be set for the first one, and only if - // `last_interaction_task_id_` wasn't already set. - if (!last_interaction_task_id_.value()) { - PerInteractionData* data = MakeGarbageCollected<PerInteractionData>(); - if (!current_event_parameters.is_new_interaction) { - // The `PerInteractionData` wasn't created for the "new interaction", but - // we still want to use the processing-end timestamp from that event. - data->user_interaction_timestamp = pending_interaction_timestamp_; - } - interaction_task_id_to_interaction_data_.insert(task.Id().value(), data); - last_interaction_task_id_ = task.Id(); - } else { - task_id_to_interaction_task_id_.insert(task.Id().value(), - last_interaction_task_id_.value()); - } + // user-initiated navigation and popstate events. Running such an event + // listener "activates" the `SoftNavigationContext` as a candidate soft + // navigation. + potential_soft_navigations_.insert(active_interaction_context_.Get()); initial_interaction_encountered_ = true; SetIsTrackingSoftNavigationHeuristicsOnDocument(true); - soft_navigation_descendant_cache_.clear(); - if (current_event_parameters.type == EventScope::Type::kNavigate) { + if (CurrentEventParameters().type == EventScope::Type::kNavigate) { SameDocumentNavigationStarted(); } } void SoftNavigationHeuristics::ProcessCustomWeakness( const LivenessBroker& info) { + if (potential_soft_navigations_.empty()) { + return; + } // When all the soft navigation tasks were garbage collected, that means that // all their descendant tasks are done, and there's no need to continue // searching for soft navigation signals, at least not until the next user @@ -611,9 +519,15 @@ // // Note: This is not allowed to do Oilpan allocations. If that's needed, this // can schedule a task or microtask to reset the heuristic. - if (has_potential_soft_navigation_task_ && - potential_soft_navigation_tasks_.empty()) { - RecordUmaForNonSoftNavigationInteractions(); + Vector<UntracedMember<SoftNavigationContext>> dead_contexts; + for (const auto& context : potential_soft_navigations_) { + if (!info.IsHeapObjectAlive(context)) { + RecordUmaForNonSoftNavigationInteraction(*context.Get()); + dead_contexts.push_back(context); + } + } + potential_soft_navigations_.RemoveAll(dead_contexts); + if (potential_soft_navigations_.empty()) { ResetHeuristic(); } } @@ -631,20 +545,37 @@ all_event_parameters_.push_back(EventParameters(is_new_interaction, type)); if (all_event_parameters_.size() == 1) { - UserInitiatedInteraction(); - // Clear the state needed to link multiple events together (e.g. keydown and - // keyup) so we don't inadvertently link a new interaction with an old one. - // Only doing this for the outermost `EventScope` will cause nested scopes - // to be considered part of the same interaction. - if (is_new_interaction) { - last_interaction_task_id_ = scheduler::TaskAttributionId(); - pending_interaction_timestamp_ = base::TimeTicks(); + // Create a new `SoftNavigationContext`, which represents a candidate soft + // navigation interaction. This context is propagated to all descendant + // tasks created within this or any nested `EventScope`. + // + // For non-"new interactions", we want to reuse the context from the initial + // "new interaction" (i.e. keydown), but will create a new one if that has + // been cleared, which can happen in tests. + if (is_new_interaction || !active_interaction_context_) { + active_interaction_context_ = + MakeGarbageCollected<SoftNavigationContext>(); } - } + // Ensure that paints would be reset, so that paint recording would continue + // despite the user interaction. + ResetPaintsIfNeeded(); + } + CHECK(active_interaction_context_.Get()); + + auto* tracker = scheduler::TaskAttributionTracker::From( + GetSupplementable()->GetIsolate()); + // `tracker` will be null if TaskAttributionInfrastructureDisabledForTesting + // is enabled. + if (!tracker) { + return SoftNavigationHeuristics::EventScope(this, + /*observer_scope=*/std::nullopt, + /*task_scope=*/std::nullopt); + } return SoftNavigationHeuristics::EventScope( - this, scheduler::TaskAttributionTracker::From( - GetSupplementable()->GetIsolate())); + this, tracker->RegisterObserver(this), + tracker->CreateTaskScope(ToScriptStateForMainWorld(GetSupplementable()), + active_interaction_context_.Get())); } void SoftNavigationHeuristics::OnSoftNavigationEventScopeDestroyed() { @@ -653,6 +584,16 @@ // handler. SetCurrentTimeAsStartTime(); + // We can't clear `active_interaction_context_` for keyboard scopes because + // subsequent non-new interaction scopes need to reuse the context. + EventScope::Type type = CurrentEventParameters().type; + if (all_event_parameters_.size() == 1) { + if (type == EventScope::Type::kNavigate || + type == EventScope::Type::kClick) { + active_interaction_context_ = nullptr; + } + } + // `SetCurrentTimeAsStartTime()` depends on `CurrentEventParameters()`, so // clear this last. all_event_parameters_.pop_back(); @@ -665,22 +606,24 @@ // /////////////////////////////////////////// SoftNavigationHeuristics::EventScope::EventScope( SoftNavigationHeuristics* heuristics, - scheduler::TaskAttributionTracker* tracker) - : heuristics_(heuristics) { + std::optional<ObserverScope> observer_scope, + std::optional<TaskScope> task_scope) + : heuristics_(heuristics), + observer_scope_(std::move(observer_scope)), + task_scope_(std::move(task_scope)) { CHECK(heuristics_); - if (tracker) { - observer_scope_ = tracker->RegisterObserver(heuristics_); - } } SoftNavigationHeuristics::EventScope::EventScope(EventScope&& other) : heuristics_(std::exchange(other.heuristics_, nullptr)), - observer_scope_(std::move(other.observer_scope_)) {} + observer_scope_(std::move(other.observer_scope_)), + task_scope_(std::move(other.task_scope_)) {} SoftNavigationHeuristics::EventScope& SoftNavigationHeuristics::EventScope::operator=(EventScope&& other) { heuristics_ = std::exchange(other.heuristics_, nullptr); observer_scope_ = std::move(other.observer_scope_); + task_scope_ = std::move(other.task_scope_); return *this; }
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h index 0c0a609..b0fbc58 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h
@@ -7,10 +7,8 @@ #include <optional> -#include "base/containers/enum_set.h" #include "base/gtest_prod_util.h" #include "base/memory/stack_allocated.h" -#include "third_party/blink/public/common/scheduler/task_attribution_id.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" @@ -20,6 +18,11 @@ #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { +namespace scheduler { +class TaskAttributionInfo; +} // namespace scheduler + +class SoftNavigationContext; namespace internal { @@ -74,13 +77,18 @@ EventScope& operator=(EventScope&&); private: + using ObserverScope = scheduler::TaskAttributionTracker::ObserverScope; + using TaskScope = scheduler::TaskAttributionTracker::TaskScope; + friend class SoftNavigationHeuristics; - EventScope(SoftNavigationHeuristics*, scheduler::TaskAttributionTracker*); + EventScope(SoftNavigationHeuristics*, + std::optional<ObserverScope>, + std::optional<TaskScope>); SoftNavigationHeuristics* heuristics_; - std::optional<scheduler::TaskAttributionTracker::ObserverScope> - observer_scope_; + std::optional<ObserverScope> observer_scope_; + std::optional<TaskScope> task_scope_; }; // Supplement boilerplate. @@ -110,37 +118,15 @@ EventScope CreateEventScope(EventScope::Type type, bool is_new_interaction); // This method is called during the weakness processing stage of garbage - // collection, and it's used to detect `potential_soft_navigation_tasks_` - // becoming empty. + // collection to remove items from `potential_soft_navigations_` and to detect + // it becoming empty, in which case the heuristic is reset. void ProcessCustomWeakness(const LivenessBroker& info); bool GetInitialInteractionEncounteredForTest() { return initial_interaction_encountered_; } - scheduler::TaskAttributionIdType GetLastInteractionTaskIdForTest() const { - return last_interaction_task_id_.value(); - } - private: - enum FlagType : uint8_t { - kURLChange, - kMainModification, - }; - - using FlagTypeSet = base::EnumSet<FlagType, kURLChange, kMainModification>; - struct PerInteractionData : public GarbageCollected<PerInteractionData> { - // The timestamp just before the event responding to the user's interaction - // started processing. In case of multiple events for a single interaction - // (e.g. a keyboard key press resulting in keydown, keypress, and keyup), - // this timestamp would be the time before processing started on the first - // event. - base::TimeTicks user_interaction_timestamp; - FlagTypeSet flag_set; - String url; - void Trace(Visitor*) const {} - }; - struct EventParameters { explicit EventParameters() = default; EventParameters(bool is_new_interaction, EventScope::Type type) @@ -150,62 +136,83 @@ EventScope::Type type = EventScope::Type::kClick; }; - void ReportSoftNavigationToMetrics(LocalFrame* frame) const; - void RecordUmaForNonSoftNavigationInteractions() const; - void CheckSoftNavigationConditions(const PerInteractionData& data); + void RecordUmaForNonSoftNavigationInteraction( + const SoftNavigationContext&) const; + void ReportSoftNavigationToMetrics(LocalFrame*, SoftNavigationContext*) const; void SetIsTrackingSoftNavigationHeuristicsOnDocument(bool value) const; - std::optional<scheduler::TaskAttributionId> - GetUserInteractionAncestorTaskIfAny(); - std::optional<scheduler::TaskAttributionId> SetFlagIfDescendantAndCheck( - FlagType); + SoftNavigationContext* GetSoftNavigationContextForCurrentTask(); void ResetHeuristic(); void ResetPaintsIfNeeded(); void CommitPreviousPaints(LocalFrame*); - void EmitSoftNavigationEntryIfAllConditionsMet(LocalFrame*); + void EmitSoftNavigationEntryIfAllConditionsMet(SoftNavigationContext*); LocalFrame* GetLocalFrameIfNotDetached() const; - void UserInitiatedInteraction(); void SetCurrentTimeAsStartTime(); void OnSoftNavigationEventScopeDestroyed(); - PerInteractionData* GetCurrentInteractionData(scheduler::TaskAttributionId); - // This must only be called when `all_event_parameters_` is non-empty. const EventParameters& CurrentEventParameters() { return all_event_parameters_.back(); } - HeapHashSet<WeakMember<const scheduler::TaskAttributionInfo>> - potential_soft_navigation_tasks_; - WTF::HashMap<scheduler::TaskAttributionIdType, - std::optional<scheduler::TaskAttributionId>> - soft_navigation_descendant_cache_; - bool did_reset_paints_ = false; - bool did_commit_previous_paints_ = false; - HeapHashMap<scheduler::TaskAttributionIdType, Member<PerInteractionData>> - interaction_task_id_to_interaction_data_; - base::TimeTicks pending_interaction_timestamp_; - std::optional<scheduler::TaskAttributionId> - last_soft_navigation_ancestor_task_; - Member<const PerInteractionData> soft_navigation_interaction_data_; - WTF::HashMap<scheduler::TaskAttributionIdType, - scheduler::TaskAttributionIdType> - task_id_to_interaction_task_id_; + // The set of ongoing potential soft navigations. `SoftNavigationContext` + // objects are added when they are the active context during an event handler + // running in an `EventScope`. Entries are stored as untraced members to do + // custom weak processing (see `ProcessCustomWeakness()`). + HashSet<UntracedMember<const SoftNavigationContext>> + potential_soft_navigations_; + + // The `SoftNavigationContext` of the "active interaction", if any. + // + // This is set to a new `SoftNavigationContext` when + // 1. an `EventScope` is created for a new interaction (click, navigation, + // and keydown) and there isn't already an active `EventScope` on the + // stack for this `SoftNavigationHeuristics`. Note that the latter + // restriction causes the same context to be reused for nested + // `EventScope`s, which occur when the navigate event occurs within the + // scope of the input event. + // + // 2. an `EventScope` is created for a non-new interaction (keypress, keyup) + // and `active_interaction_context_` isn't set. These events typically + // follow a keydown, in which case the context created for that will be + // reused, but the context can be cleared if, for example, a click + // happens while a key is held. + // + // This is cleared when the outermost `EventScope` is destroyed if the scope + // type is click or navigate. For keyboard events, which have multiple related + // events, this remains alive until the next interaction. + Member<SoftNavigationContext> active_interaction_context_; + + // The `SoftNavigationContext` associated with an active uncommitted same + // document navigation. This set when `SameDocumentNavigationStarted()` is + // called, and it's cleared when the navigation commits, the heuristic is + // reset, or indirectly via GC when the navigation is cancelled and any + // references in propagated tasks are released. + // + // TODO(crbug.com/40942324): consider removing this and plumbing it through + // `SameDocumentNavigationCommitted()`. + WeakMember<SoftNavigationContext> + uncommitted_same_document_navigation_context_; + + // The last soft navigation detected, which could be pending (not emitted) + // until `paint_conditions_met_` is true. + // + // TODO(crbug.com/1510706): Remove this is if `paint_conditions_met_` isn't + // reinstated since it is cleared immediately after emitting the entry. + WeakMember<SoftNavigationContext> last_detected_soft_navigation_; + uint32_t soft_navigation_count_ = 0; uint64_t softnav_painted_area_ = 0; uint64_t initial_painted_area_ = 0; uint64_t viewport_area_ = 0; - scheduler::TaskAttributionId last_interaction_task_id_; - bool soft_navigation_conditions_met_ = false; + bool did_commit_previous_paints_ = false; bool paint_conditions_met_ = false; bool initial_interaction_encountered_ = false; + // `SoftNavigationEventScope`s can be nested in case a click/keyboard event // synchronously initiates a navigation. `all_event_parameters_` stores one // `EventParameters` per scope, with the most recent one in the back. WTF::Deque<EventParameters> all_event_parameters_; - // Used to synchronize resetting the heuristic when - // `potential_soft_navigation_tasks_` becomes empty during GC. - bool has_potential_soft_navigation_task_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc index 3be2087..3f749875 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc
@@ -43,6 +43,12 @@ return ToScriptStateForMainWorld(page_holder_->GetDocument().GetFrame()); } + bool IsDocumentTrackingSoftNavigations() { + return LocalDOMWindow::From(GetScriptStateForTest()) + ->document() + ->IsTrackingSoftNavigationHeuristics(); + } + private: test::TaskEnvironment task_environment_; std::unique_ptr<DummyPageHolder> page_holder_; @@ -63,11 +69,12 @@ auto* tracker = scheduler::TaskAttributionTracker::From( GetScriptStateForTest()->GetIsolate()); ASSERT_TRUE(tracker); - // NextId() required so that the first task ID is non-zero (because we hash on - // key). - auto* task = tracker->CreateTaskAttributionInfoForTest( - scheduler::TaskAttributionId().NextId()); - test_heuristics->OnCreateTaskScope(*task); + { + // Simulate a top-level event dispatch with no context to propagate. + std::optional<TaskScope> task_scope = + tracker->MaybeCreateTaskScopeForCallback(GetScriptStateForTest(), + nullptr); + } ASSERT_TRUE(test_heuristics->GetInitialInteractionEncounteredForTest()); } @@ -145,16 +152,23 @@ Persistent<scheduler::TaskAttributionInfo> root_task = nullptr; // Simulate a click. { + EXPECT_FALSE(IsDocumentTrackingSoftNavigations()); SoftNavigationHeuristics::EventScope event_scope( heuristics->CreateEventScope( SoftNavigationHeuristics::EventScope::Type::kClick, /*is_new_interaction=*/true)); - TaskScope task_scope = tracker->CreateTaskScope( - script_state, /*parent_task=*/nullptr, TaskScopeType::kCallback); + + // Simulate a top-level event dispatch with no context to propagate. + std::optional<TaskScope> task_scope = + tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); + // This won't create a new task scope because there's already one on the + // stack to propagate the soft navigation context, but it should notify + // `heuristics`. + EXPECT_FALSE(task_scope); root_task = tracker->RunningTask(); } EXPECT_TRUE(root_task); - EXPECT_GT(heuristics->GetLastInteractionTaskIdForTest(), 0u); + EXPECT_TRUE(IsDocumentTrackingSoftNavigations()); // Simulate a descendant task. Persistent<scheduler::TaskAttributionInfo> descendant_task = nullptr; @@ -165,21 +179,23 @@ } EXPECT_TRUE(descendant_task); + EXPECT_TRUE(IsDocumentTrackingSoftNavigations()); + EXPECT_EQ(root_task.Get(), descendant_task.Get()); + root_task = nullptr; ThreadState::Current()->CollectAllGarbageForTesting(); // The heuristics still should not have been reset since there is a live // root task, which is being held onto by its descendant task. - EXPECT_GT(heuristics->GetLastInteractionTaskIdForTest(), 0u); + EXPECT_TRUE(IsDocumentTrackingSoftNavigations()); // Finally, this should allow the click task to be GCed, which should cause // the heuristics to be reset. descendant_task = nullptr; ThreadState::Current()->CollectAllGarbageForTesting(); - EXPECT_EQ(heuristics->GetLastInteractionTaskIdForTest(), 0u); + EXPECT_FALSE(IsDocumentTrackingSoftNavigations()); } TEST_F(SoftNavigationHeuristicsTest, NestedEventScopesAreMerged) { - auto current_task_id = scheduler::TaskAttributionId().NextId(); auto* heuristics = CreateSoftNavigationHeuristicsForTest(); SoftNavigationHeuristics::EventScope outer_event_scope( @@ -190,26 +206,29 @@ GetScriptStateForTest()->GetIsolate()); ASSERT_TRUE(tracker); - auto* task1 = tracker->CreateTaskAttributionInfoForTest(current_task_id); - heuristics->OnCreateTaskScope(*task1); - - scheduler::TaskAttributionIdType interaction_id1 = - heuristics->GetLastInteractionTaskIdForTest(); - EXPECT_GT(interaction_id1, 0u); - - current_task_id = current_task_id.NextId(); - EXPECT_NE(current_task_id.value(), interaction_id1); + auto* script_state = GetScriptStateForTest(); + SoftNavigationContext* context1 = nullptr; + { + std::optional<TaskScope> task_scope = + tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); + context1 = tracker->RunningTask()->GetSoftNavigationContext(); + } + EXPECT_TRUE(context1); SoftNavigationHeuristics::EventScope inner_event_scope( heuristics->CreateEventScope( SoftNavigationHeuristics::EventScope::Type::kNavigate, /*is_new_interaction=*/true)); - auto* task2 = tracker->CreateTaskAttributionInfoForTest(current_task_id); - heuristics->OnCreateTaskScope(*task2); - scheduler::TaskAttributionIdType interaction_id2 = - heuristics->GetLastInteractionTaskIdForTest(); - EXPECT_EQ(interaction_id1, interaction_id2); + SoftNavigationContext* context2 = nullptr; + { + std::optional<TaskScope> task_scope = + tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); + context2 = tracker->RunningTask()->GetSoftNavigationContext(); + } + EXPECT_TRUE(context2); + + EXPECT_EQ(context1, context2); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_debug_utils.cc b/third_party/blink/renderer/modules/accessibility/ax_debug_utils.cc index c2d0c61..f89a6f7 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_debug_utils.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_debug_utils.cc
@@ -98,8 +98,8 @@ void CheckTreeConsistency( AXObjectCacheImpl& cache, - ui::AXTreeSerializer<AXObject*, - HeapVector<Member<AXObject>>, + ui::AXTreeSerializer<const AXObject*, + HeapVector<Member<const AXObject>>, ui::AXTreeUpdate*, ui::AXTreeData*, ui::AXNodeData>& serializer, @@ -133,7 +133,7 @@ HeapHashMap<AXID, Member<AXObject>>& all_objects = cache.GetObjects(); for (const auto& id_to_object_entry : all_objects) { AXObject* obj = id_to_object_entry.value; - if (obj->LastKnownIsIncludedInTreeValue()) { + if (obj->IsIncludedInTree()) { if (!serializer.IsInClientTree(obj)) { if (obj->IsMissingParent()) { msg << "\n* Included node not serialized, is missing parent: " @@ -142,7 +142,7 @@ msg << "\n* Included node not serialized, in closed document: " << obj; } else { - bool included_state_stale = !obj->AccessibilityIsIncludedInTree(); + bool included_state_stale = !obj->IsIncludedInTree(); msg << "\n* Included node not serialized: " << obj; if (included_state_stale) { msg << "\n Included state was stale."; @@ -156,10 +156,10 @@ AXObject* obj = cache.ObjectFromAXID(id); if (!obj) { msg << "\n* Serialized node does not exist: " << id; - if (AXObject* parent = serializer.ParentOf(id)) { + if (const AXObject* parent = serializer.ParentOf(id)) { msg << "\n* Parent = " << parent; } - } else if (!obj->LastKnownIsIncludedInTreeValue()) { + } else if (!obj->IsIncludedInTree()) { msg << "\n* Serialized an unincluded node: " << obj; } }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_debug_utils.h b/third_party/blink/renderer/modules/accessibility/ax_debug_utils.h index f88d3ed..ea9ff72 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_debug_utils.h +++ b/third_party/blink/renderer/modules/accessibility/ax_debug_utils.h
@@ -24,8 +24,8 @@ // nodes as the AXObjectCache thinks exists. void CheckTreeConsistency( AXObjectCacheImpl& cache, - ui::AXTreeSerializer<AXObject*, - HeapVector<Member<AXObject>>, + ui::AXTreeSerializer<const AXObject*, + HeapVector<Member<const AXObject>>, ui::AXTreeUpdate*, ui::AXTreeData*, ui::AXNodeData>& serializer,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc index c6a64870..2eca581e 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc
@@ -84,17 +84,17 @@ out_bounds_in_container.Offset(-parent_bounding_box.OffsetFromOrigin()); } -bool AXInlineTextBox::ComputeAccessibilityIsIgnored( +bool AXInlineTextBox::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { AXObject* parent = ParentObject(); if (!parent) return false; - if (!parent->AccessibilityIsIgnored()) + if (!parent->IsIgnored()) return false; if (ignored_reasons) - parent->ComputeAccessibilityIsIgnored(ignored_reasons); + parent->ComputeIsIgnored(ignored_reasons); return true; } @@ -416,7 +416,7 @@ return static_cast<int>(inline_text_box_->Len()); } -void AXInlineTextBox::ClearChildren() const { +void AXInlineTextBox::ClearChildren() { // An AXInlineTextBox has no children to clear. }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h index d599c9c4..d4041b6 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h +++ b/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h
@@ -72,7 +72,7 @@ NOTREACHED(); return ax::mojom::blink::Role::kInlineTextBox; } - void ClearChildren() const override; + void ClearChildren() override; AbstractInlineTextBox* GetInlineTextBox() const override; protected: @@ -87,7 +87,7 @@ void AddChildren() override {} private: - bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; + bool ComputeIsIgnored(IgnoredReasons* = nullptr) const override; Member<AbstractInlineTextBox> inline_text_box_; };
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc index f419159..b5564799 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
@@ -109,7 +109,7 @@ AXNodeObject::ChildrenChangedWithCleanLayout(); } -void AXMenuList::SetNeedsToUpdateChildren(bool update) const { +void AXMenuList::SetNeedsToUpdateChildren(bool update) { if (!update) { AXNodeObject::SetNeedsToUpdateChildren(false); return; @@ -125,7 +125,7 @@ AXNodeObject::SetNeedsToUpdateChildren(); } -void AXMenuList::ClearChildren() const { +void AXMenuList::ClearChildren() { if (popup_) { popup_->ClearChildren(); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list.h b/third_party/blink/renderer/modules/accessibility/ax_menu_list.h index 850a719..46f25fbc 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list.h +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list.h
@@ -46,8 +46,8 @@ AccessibilityExpanded IsExpanded() const final; bool OnNativeClickAction() override; void ChildrenChangedWithCleanLayout() override; - void SetNeedsToUpdateChildren(bool update = true) const override; - void ClearChildren() const override; + void SetNeedsToUpdateChildren(bool update = true) override; + void ClearChildren() override; void Detach() override; void DidUpdateActiveOption();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc index 0d3c63b..c2a4968 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
@@ -145,7 +145,7 @@ // TODO(aleventhal) This override could go away, but it will cause a lot of // test changes, as invisible options inside of a collapsed <select> will become // ignored since they have no layout object. -bool AXMenuListOption::ComputeAccessibilityIsIgnored( +bool AXMenuListOption::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { if (IsDetached()) { NOTREACHED(); @@ -164,7 +164,7 @@ } return !ParentObject() || - ParentObject()->ComputeAccessibilityIsIgnored(ignored_reasons); + ParentObject()->ComputeIsIgnored(ignored_reasons); } void AXMenuListOption::GetRelativeBounds(
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h index 5cbc02a..2c9e2da 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h
@@ -69,7 +69,7 @@ ax::mojom::NameFrom&, AXRelatedObjectVector*, NameSources*) const override; - bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; + bool ComputeIsIgnored(IgnoredReasons* = nullptr) const override; }; template <>
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc index 55f0511..27a142c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
@@ -66,12 +66,12 @@ : kRestrictionNone; } -bool AXMenuListPopup::ComputeAccessibilityIsIgnored( +bool AXMenuListPopup::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { // Base whether the menupopup is ignored on the containing <select>. if (parent_) { parent_->UpdateCachedAttributeValuesIfNeeded(); - return parent_->ComputeAccessibilityIsIgnored(ignored_reasons); + return parent_->ComputeIsIgnored(ignored_reasons); } return kIgnoreObject; @@ -143,7 +143,7 @@ for (auto* const option_element : html_select_element->GetOptionList()) { AXMenuListOption* option = MenuListOptionAXObject(option_element); CHECK_EQ(option->ParentObject(), this); - if (option && option->AccessibilityIsIncludedInTree()) { + if (option && option->IsIncludedInTree()) { DCHECK(!option->IsDetached()); children_.push_back(option); } @@ -200,7 +200,7 @@ cache.MarkAXSubtreeDirtyWithCleanLayout(ParentObject()); } -AXObject* AXMenuListPopup::ActiveDescendant() { +AXObject* AXMenuListPopup::ActiveDescendant() const { // Some Windows screen readers don't work properly if the active descendant // gets the focus before they focus the list menu popup. if (parent_ && !parent_->IsFocused())
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.h b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.h index 81877b4..febbfb7a 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.h +++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.h
@@ -53,7 +53,7 @@ void DidUpdateActiveOption(int option_index, bool fire_notifications = true); void DidShow(); void DidHide(); - AXObject* ActiveDescendant() final; + AXObject* ActiveDescendant() const final; AXObject* owner() const { return owner_; } private: @@ -64,7 +64,7 @@ bool IsVisible() const override; bool OnNativeClickAction() override; void AddChildren() override; - bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; + bool ComputeIsIgnored(IgnoredReasons* = nullptr) const override; AXMenuListOption* MenuListOptionAXObject(HTMLElement*); int GetSelectedIndex() const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index f57e71c..a1501a6 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -420,7 +420,7 @@ // Inline text boxes are included if and only if the parent is unignored. // If the parent is ignored but included in tree, the inline textbox is // still withheld. - return !obj->LastKnownIsIgnoredValue(); + return !obj->IsIgnored(); } bool HasLayoutText(const blink::AXObject* obj) { @@ -585,7 +585,7 @@ base::Milliseconds(100)); } -AXObject* AXNodeObject::ActiveDescendant() { +AXObject* AXNodeObject::ActiveDescendant() const { Element* element = GetElement(); if (!element) return nullptr; @@ -944,7 +944,7 @@ return kDefaultBehavior; } -bool AXNodeObject::ComputeAccessibilityIsIgnored( +bool AXNodeObject::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { Node* node = GetNode(); @@ -1051,7 +1051,7 @@ ContainerListMarkerIncludingIgnored(); if (list_marker_object && (list_marker_object->GetLayoutObject()->IsListMarkerForSummary() || - !list_marker_object->AccessibilityIsIgnored())) { + !list_marker_object->IsIgnored())) { if (ignored_reasons) { ignored_reasons->push_back(IgnoredReason(kAXPresentational)); } @@ -1064,8 +1064,8 @@ // This means that other interesting objects inside the <label> will // cause the text to be unignored. if (IsUsedForLabelOrDescription()) { - AXObject* ancestor = ParentObject(); - while (ancestor && ancestor->AccessibilityIsIgnored()) { + const AXObject* ancestor = ParentObject(); + while (ancestor && ancestor->IsIgnored()) { if (ancestor->RoleValue() == ax::mojom::blink::Role::kLabelText) { if (ignored_reasons) { ignored_reasons->push_back(IgnoredReason(kAXPresentational)); @@ -2312,7 +2312,7 @@ // Only aria-labelledby and aria-describedby can target hidden elements. if (!child) continue; - if (child->AccessibilityIsIgnored() && + if (child->IsIgnored() && property != AOMRelationListProperty::kLabeledBy && property != AOMRelationListProperty::kDescribedBy) { continue; @@ -3249,7 +3249,7 @@ #endif // Usually won't be ignored, but could be e.g. if aria-hidden. - if (ax_target->AccessibilityIsIgnored()) + if (ax_target->IsIgnored()) return nullptr; return ax_target; @@ -3356,7 +3356,7 @@ for (AXObject* child : parent->UnignoredChildren()) { DCHECK(child); if (child->RoleValue() == ax::mojom::blink::Role::kRadioButton && - child->AccessibilityIsIncludedInTree()) { + child->IsIncludedInTree()) { radio_buttons.push_back(child); } } @@ -4569,7 +4569,7 @@ // No visible rendered text -- must be whitespace. // Either it is useful whitespace for separating words or not. if (layout_text->IsAllCollapsibleWhitespace()) { - if (LastKnownIsIgnoredValue()) { + if (IsIgnored()) { return ""; } // If no textboxes, this was whitespace at the line's end. @@ -4816,10 +4816,7 @@ ax::mojom::blink::NameFrom last_used_name_from = ax::mojom::blink::NameFrom::kNone; - // Ensure that if this node needs to invalidate its children (e.g. due to - // included in tree status change), that we do it now, rather than while - // traversing the children. - UpdateCachedAttributeValuesIfNeeded(); + CHECK(!NeedsToUpdateCachedValues()); const AXObjectVector& children = ChildrenIncludingIgnored(); #if defined(AX_FAIL_FAST_BUILD) @@ -4889,7 +4886,7 @@ bool AXNodeObject::IsNameFromLabelElement(HTMLElement* control) { // This duplicates some logic from TextAlternative()/NativeTextAlternative(), // but is necessary because IsNameFromLabelElement() needs to be called from - // ComputeAccessibilityIsIgnored(), which isn't allowed to call + // ComputeIsIgnored(), which isn't allowed to call // AXObjectCache().GetOrCreate() in random places in the tree. if (!control) @@ -5227,7 +5224,7 @@ while (!work_queue.empty()) { AXObject* work_obj = AXObjectCache().ObjectFromAXID(work_queue.front()); work_queue.pop(); - if (!work_obj || !work_obj->LastKnownIsIncludedInTreeValue()) { + if (!work_obj || !work_obj->IsIncludedInTree()) { continue; } @@ -5614,7 +5611,7 @@ bool is_from_aria_owns) { if (!child) return; - DCHECK(child->LastKnownIsIncludedInTreeValue()); + DCHECK(child->CachedIsIncludedInTree()); AddChild(child, is_from_aria_owns); } @@ -5646,11 +5643,11 @@ child->UpdateCachedAttributeValuesIfNeeded( /*notify_parent_of_ignored_changes*/ false); - if (!child->LastKnownIsIncludedInTreeValue()) { + if (!child->IsIncludedInTree()) { DCHECK(!is_from_aria_owns) << "Owned elements must be in tree: " << child << "\nRecompute included in tree: " - << child->ComputeAccessibilityIsIgnoredButIncludedInTree(); + << child->ComputeIsIgnoredButIncludedInTree(); // Get the ignored child's children and add to children of ancestor // included in tree. This will recurse if necessary, skipping levels of @@ -6137,7 +6134,7 @@ AXObjectVector error_messages; for (Element* element : elements_from_attribute) { AXObject* obj = AXObjectCache().Get(element); - if (obj && !obj->AccessibilityIsIgnored()) { + if (obj && !obj->IsIgnored()) { error_messages.push_back(obj); } } @@ -7390,7 +7387,7 @@ // non-layout children. result = result->ElementAccessibilityHitTest(point); - while (result && result->AccessibilityIsIgnored()) { + while (result && result->IsIgnored()) { // If this element is the label of a control, a hit test should return the // control. The label is ignored because it's already reflected in the name. if (auto* label = DynamicTo<HTMLLabelElement>(result->GetNode())) { @@ -7449,7 +7446,7 @@ // the inline-block element. We exclude list markers since those technically // fulfill the inline-block condition. AXObject* ax_object = start_object->AXObjectCache().Get(current_node); - if (ax_object && ax_object->AccessibilityIsIncludedInTree() && + if (ax_object && ax_object->IsIncludedInTree() && !current_node->IsMarkerPseudoElement()) { if (ax_object->GetLayoutObject() && ax_object->GetLayoutObject()->IsInline() && @@ -7466,7 +7463,7 @@ AXObject* tentative_child = start_object->AXObjectCache().Get(current_node); - if (tentative_child && tentative_child->AccessibilityIsIncludedInTree()) { + if (tentative_child && tentative_child->IsIncludedInTree()) { result = tentative_child; } } @@ -7476,7 +7473,7 @@ // such as an AXInlineTextBox. // Relevant static text or pseudo element is always included. - if (!result->AccessibilityIsIncludedInTree()) { + if (!result->IsIncludedInTree()) { return nullptr; } @@ -7510,7 +7507,7 @@ // A list marker should be followed by a list item on the same line. // Note that pseudo content is always included in the tree, so // NextSiblingIncludingIgnored() will succeed. - if (AccessibilityIsIncludedInTree()) { + if (IsIncludedInTree()) { return GetFirstInlineBlockOrDeepestInlineAXChildInLayoutTree( NextSiblingIncludingIgnored(), true); } @@ -7619,7 +7616,7 @@ return nullptr; } - AXObject* previous_sibling = AccessibilityIsIncludedInTree() + AXObject* previous_sibling = IsIncludedInTree() ? PreviousSiblingIncludingIgnored() : nullptr; if (previous_sibling && previous_sibling->GetLayoutObject() &&
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index 2ba5bd4..eb59b35 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -80,11 +80,11 @@ AXObjectInclusion ShouldIncludeBasedOnSemantics( IgnoredReasons* = nullptr) const; - bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; + bool ComputeIsIgnored(IgnoredReasons* = nullptr) const override; ax::mojom::blink::Role DetermineRoleValue() override; ax::mojom::blink::Role NativeRoleIgnoringAria() const override; void AlterSliderOrSpinButtonValue(bool increase); - AXObject* ActiveDescendant() override; + AXObject* ActiveDescendant() const override; String AriaAccessibilityDescription() const; String AutoComplete() const override; void AccessibilityChildrenFromAOMProperty(AOMRelationListProperty,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index e26a21d..89c0d3a3 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -479,7 +479,7 @@ DCHECK(node_data); std::vector<int32_t> ids; for (const auto& obj : objects) { - if (!obj->AccessibilityIsIgnored()) + if (!obj->IsIgnored()) ids.push_back(obj->AXObjectID()); } if (!ids.empty()) @@ -609,14 +609,14 @@ --number_of_live_ax_objects_; } -void AXObject::SetHasDirtyDescendants(bool dirty) const { - CHECK(!dirty || LastKnownIsIncludedInTreeValue()) +void AXObject::SetHasDirtyDescendants(bool dirty) { + CHECK(!dirty || CachedIsIncludedInTree()) << "Only included nodes can be marked as having dirty descendants: " << this; has_dirty_descendants_ = dirty; } -void AXObject::SetAncestorsHaveDirtyDescendants() const { +void AXObject::SetAncestorsHaveDirtyDescendants() { CHECK(!IsDetached()); CHECK(!AXObjectCache().HasBeenDisposed()); if (AXObjectCache().IsFrozen()) { @@ -647,13 +647,13 @@ // the parent chain while marking everything dirty is actually against // the point, because all child-parent relationships will be rebuilt // from the top down. - if (LastKnownIsIncludedInTreeValue()) { + if (CachedIsIncludedInTree()) { SetHasDirtyDescendants(true); } return; } - const AXObject* ancestor = this; + AXObject* ancestor = this; while (true) { ancestor = ancestor->CachedParentObject(); @@ -663,12 +663,12 @@ DCHECK(!ancestor->IsDetached()); // We need to to continue setting bits through AX objects for which - // LastKnownIsIncludedInTreeValue is false, since those objects are omitted + // IsIncludedInTree is false, since those objects are omitted // from the generated tree. However, don't set the bit on unincluded // objects, during the clearing phase in // AXObjectCacheImpl::UpdateTreeIfNeeded(), only included nodes are // visited. - if (!ancestor->LastKnownIsIncludedInTreeValue()) { + if (!ancestor->CachedIsIncludedInTree()) { continue; } if (ancestor->has_dirty_descendants_) { @@ -683,7 +683,7 @@ bool fail = false; for (auto* obj = CachedParentObject(); obj; obj = obj->CachedParentObject()) { - if (obj->LastKnownIsIncludedInTreeValue() && + if (obj->CachedIsIncludedInTree() && !obj->has_dirty_descendants_) { fail = true; break; @@ -804,7 +804,8 @@ return GetNode() && GetNode() == &AXObjectCache().GetDocument(); } -void AXObject::SetParent(AXObject* new_parent) const { +void AXObject::SetParent(AXObject* new_parent) { + CHECK(!AXObjectCache().IsFrozen()); #if DCHECK_IS_ON() if (!new_parent && !IsRoot()) { std::ostringstream message; @@ -1342,7 +1343,7 @@ } // namespace void AXObject::Serialize(ui::AXNodeData* node_data, - ui::AXMode accessibility_mode) { + ui::AXMode accessibility_mode) const { // Reduce redundant ancestor chain walking for display lock computations. auto memoization_scope = DisplayLockUtilities::CreateLockCheckMemoizationScope(); @@ -1353,15 +1354,15 @@ PreSerializationConsistencyCheck(); // Serialize a few things that we need even for ignored nodes. - bool is_focusable = CanSetFocusAttribute(); - if (is_focusable) + if (CanSetFocusAttribute()) { node_data->AddState(ax::mojom::blink::State::kFocusable); + } bool is_visible = IsVisible(); if (!is_visible) node_data->AddState(ax::mojom::blink::State::kInvisible); - if (is_visible || is_focusable) { + if (is_visible || CanSetFocusAttribute()) { // If the author applied the ARIA "textbox" role on something that is not // (currently) editable, this may be a read-only rich-text object. Or it // might just be bad authoring. Either way, we want to expose its @@ -1405,10 +1406,10 @@ // Return early. The following attributes are unnecessary for ignored nodes. // Exception: focusable ignored nodes are fully serialized, so that reasonable // verbalizations can be made if they actually receive focus. - if (AccessibilityIsIgnored()) { + if (IsIgnored()) { node_data->AddState(ax::mojom::blink::State::kIgnored); // Early return for ignored, unfocusable nodes, avoiding unnecessary work. - if (!is_focusable) { + if (!CanSetFocusAttribute()) { // The name is important for exposing the selection around ignored nodes. // TODO(accessibility) Remove this and still pass this // content_browsertest: @@ -1446,7 +1447,7 @@ // Return early. The following attributes are unnecessary for ignored nodes. // Exception: focusable ignored nodes are fully serialized, so that reasonable // verbalizations can be made if they actually receive focus. - if (AccessibilityIsIgnored() && + if (IsIgnored() && !node_data->HasState(ax::mojom::blink::State::kFocusable)) { return; } @@ -1496,7 +1497,7 @@ bounds.transform = std::make_unique<gfx::Transform>(container_transform); } -void AXObject::SerializeActionAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeActionAttributes(ui::AXNodeData* node_data) const { if (CanSetValueAttribute()) node_data->AddAction(ax::mojom::blink::Action::kSetValue); if (IsSlider()) { @@ -1513,7 +1514,7 @@ } } -void AXObject::SerializeChildTreeID(ui::AXNodeData* node_data) { +void AXObject::SerializeChildTreeID(ui::AXNodeData* node_data) const { // If a child tree has explicitly been stitched at this object via the // `ax::mojom::blink::Action::kStitchChildTree`, then override any child trees // coming from HTML. @@ -1566,7 +1567,7 @@ node_data->AddChildTreeId(child_tree_id); } -void AXObject::SerializeChooserPopupAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeChooserPopupAttributes(ui::AXNodeData* node_data) const { AXObject* chooser_popup = ChooserPopup(); if (!chooser_popup) return; @@ -1579,7 +1580,7 @@ ax::mojom::blink::IntListAttribute::kControlsIds, controls_ids); } -void AXObject::SerializeColorAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeColorAttributes(ui::AXNodeData* node_data) const { // Text attributes. if (RGBA32 bg_color = BackgroundColor()) { node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kBackgroundColor, @@ -1590,7 +1591,7 @@ node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kColor, color); } -void AXObject::SerializeElementAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeElementAttributes(ui::AXNodeData* node_data) const { Element* element = GetElement(); if (!element) return; @@ -1608,7 +1609,7 @@ node_data, ax::mojom::blink::StringAttribute::kRole, role_str); } -void AXObject::SerializeHTMLTagAndClass(ui::AXNodeData* node_data) { +void AXObject::SerializeHTMLTagAndClass(ui::AXNodeData* node_data) const { Element* element = GetElement(); if (!element) { if (IsA<Document>(GetNode())) { @@ -1628,7 +1629,7 @@ } } -void AXObject::SerializeHTMLAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeHTMLAttributes(ui::AXNodeData* node_data) const { Element* element = GetElement(); DCHECK(element); for (const Attribute& attr : element->Attributes()) { @@ -1673,7 +1674,7 @@ ax::mojom::blink::IntListAttribute::kWordEnds, word_ends, node_data); } -void AXObject::SerializeLangAttribute(ui::AXNodeData* node_data) { +void AXObject::SerializeLangAttribute(ui::AXNodeData* node_data) const { AXObject* parent = ParentObject(); if (Language().length()) { // TODO(chrishall): should we still trim redundant languages off here? @@ -1684,7 +1685,7 @@ } } -void AXObject::SerializeListAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeListAttributes(ui::AXNodeData* node_data) const { if (SetSize()) { node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kSetSize, SetSize()); @@ -1798,7 +1799,7 @@ node_data, ax::mojom::blink::StringAttribute::kPlaceholder, placeholder); } -void AXObject::SerializeScreenReaderAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeScreenReaderAttributes(ui::AXNodeData* node_data) const { if (ui::IsText(RoleValue())) { // Don't serialize these attributes on text, where it is uninteresting. return; @@ -2007,7 +2008,7 @@ } } -void AXObject::SerializeScrollAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeScrollAttributes(ui::AXNodeData* node_data) const { // Only mark as scrollable if user has actual scrollbars to use. node_data->AddBoolAttribute(ax::mojom::blink::BoolAttribute::kScrollable, IsUserScrollable()); @@ -2032,7 +2033,7 @@ max_scroll_offset.y()); } -void AXObject::SerializeSparseAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeSparseAttributes(ui::AXNodeData* node_data) const { if (IsVirtualObject()) { AccessibleNode* accessible_node = GetAccessibleNode(); if (accessible_node) { @@ -2070,7 +2071,7 @@ } } -void AXObject::SerializeStyleAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeStyleAttributes(ui::AXNodeData* node_data) const { // Only serialize font family if there is one, and it is different from the // parent. Use the value from computed style first since that is a fast lookup // and comparison, and serialize the user-friendly name at points in the tree @@ -2142,7 +2143,7 @@ } } -void AXObject::SerializeTableAttributes(ui::AXNodeData* node_data) { +void AXObject::SerializeTableAttributes(ui::AXNodeData* node_data) const { if (ui::IsTableLike(RoleValue())) { int aria_colcount = AriaColumnCount(); if (aria_colcount) { @@ -2199,7 +2200,7 @@ // Attributes that don't need to be serialized on ignored nodes. void AXObject::SerializeUnignoredAttributes(ui::AXNodeData* node_data, - ui::AXMode accessibility_mode) { + ui::AXMode accessibility_mode) const { AccessibilityExpanded expanded = IsExpanded(); if (expanded) { if (expanded == kExpandedCollapsed) @@ -2457,13 +2458,13 @@ // helps identify focusable options in the listbox using activedescendant // detection, even though the focus is on the textbox and not on the listbox // ancestor. -AXObject* AXObject::GetControlsListboxForTextfieldCombobox() { +AXObject* AXObject::GetControlsListboxForTextfieldCombobox() const { // Only perform work for textfields. if (!ui::IsTextField(RoleValue())) return nullptr; // Object is ignored for some reason, most likely hidden. - if (AccessibilityIsIgnored()) { + if (IsIgnored()) { return nullptr; } @@ -2522,7 +2523,7 @@ } const AtomicString& AXObject::GetRoleStringForSerialization( - ui::AXNodeData* node_data) { + ui::AXNodeData* node_data) const { // All ARIA roles are exposed in xml-roles. if (const AtomicString& role_str = GetAOMPropertyOrARIAAttribute(AOMStringProperty::kRole)) { @@ -2673,7 +2674,7 @@ // accessible children have not been calculated. Rather than force calculation // there, wait until we have the full tree. if (role_ == ax::mojom::blink::Role::kSvgRoot && - AccessibilityIsIncludedInTree() && !UnignoredChildCount()) { + IsIncludedInTree() && !UnignoredChildCount()) { return ax::mojom::blink::Role::kImage; } @@ -3083,7 +3084,14 @@ return false; } -bool AXObject::AccessibilityIsIgnored() const { +bool AXObject::IsIgnored() const { + DCHECK(cached_is_ignored_ || !IsDetached()) + << "A detached object should always indicate that it is ignored so that " + "it won't ever accidentally be included in the tree."; + return cached_is_ignored_; +} + +bool AXObject::IsIgnored() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); #if defined(AX_FAIL_FAST_BUILD) @@ -3101,19 +3109,33 @@ return cached_is_ignored_; } -bool AXObject::AccessibilityIsIgnoredButIncludedInTree() const { +bool AXObject::IsIgnoredButIncludedInTree() const { + return cached_is_ignored_but_included_in_tree_; +} + +bool AXObject::IsIgnoredButIncludedInTree() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); return cached_is_ignored_but_included_in_tree_; } -// AccessibilityIsIncludedInTree should be true for all nodes that should be +// IsIncludedInTree should be true for all nodes that should be // included in the tree, even if they are ignored -bool AXObject::AccessibilityIsIncludedInTree() const { - CheckCanAccessCachedValues(); +bool AXObject::IsIncludedInTree() const { + if (!IsIgnored() || IsIgnoredButIncludedInTree()) { + return true; + } + DCHECK(!IsDetached()); + return false; +} - return !AccessibilityIsIgnored() || AccessibilityIsIgnoredButIncludedInTree(); +bool AXObject::IsIncludedInTree() { + return !IsIgnored() || IsIgnoredButIncludedInTree(); +} + +bool AXObject::CachedIsIncludedInTree() { + return const_cast<const AXObject*>(this)->IsIncludedInTree(); } void AXObject::CheckCanAccessCachedValues() const { @@ -3134,7 +3156,7 @@ } void AXObject::UpdateCachedAttributeValuesIfNeeded( - bool notify_parent_of_ignored_changes) const { + bool notify_parent_of_ignored_changes) { if (IsDetached()) { cached_is_ignored_ = true; cached_is_ignored_but_included_in_tree_ = false; @@ -3225,9 +3247,9 @@ cached_can_set_focus_attribute_ = ComputeCanSetFocusAttribute(); // Must be computed before is_used_for_label_or_description computation. - bool was_included_in_tree = LastKnownIsIncludedInTreeValue(); - bool is_ignored = ComputeAccessibilityIsIgnored(); - if (is_ignored != LastKnownIsIgnoredValue()) { + bool was_included_in_tree = IsIncludedInTree(); + bool is_ignored = ComputeIsIgnored(); + if (is_ignored != IsIgnored()) { // Presence of inline text children depends on ignored state. if (ui::CanHaveInlineTextBoxChildren(RoleValue())) { is_changing_inherited_values = true; @@ -3245,7 +3267,7 @@ // This depends on cached_is_used_for_label_or_description_. bool is_ignored_but_included_in_tree = - is_ignored && ComputeAccessibilityIsIgnoredButIncludedInTree(); + is_ignored && ComputeIsIgnoredButIncludedInTree(); bool is_included_in_tree = !is_ignored || is_ignored_but_included_in_tree; bool included_in_tree_changed = is_included_in_tree != was_included_in_tree; bool notify_included_in_tree_changed = false; @@ -3288,7 +3310,7 @@ // - Inline text boxes: their "included in tree" state is entirely dependent // on their static text parent. // This must be called before cached_is_ignored_* are updated, otherwise a - // performance optimization depending on LastKnownIsIncludedInTreeValue() + // performance optimization depending on IsIncludedInTree() // may misfire. if (RoleValue() != ax::mojom::blink::Role::kInlineTextBox) { if (notify_included_in_tree_changed) { @@ -3304,8 +3326,7 @@ // Must defer it, otherwise it can cause reentry into // UpdateCachedAttributeValuesIfNeeded() on |this|. // ParentObjectUnignored()->SetNeedsToUpdateChildren(); - AXObjectCache().ChildrenChangedOnAncestorOf( - const_cast<AXObject*>(this)); + AXObjectCache().ChildrenChangedOnAncestorOf(this); } } else if (included_in_tree_changed && AXObjectCache().UpdatingTree()) { // In some cases changes to inherited properties can cause an object @@ -3324,7 +3345,6 @@ // Compute live region root, which can be from any ARIA live value, including // "off", or from an automatic ARIA live value, e.g. from role="status". - // TODO(dmazzoni): remove this const_cast. AXObject* previous_live_region_root = cached_live_region_root_; if (GetNode() && IsA<Document>(GetNode())) { // The document root is never a live region root. @@ -3334,8 +3354,8 @@ cached_live_region_root_ = nullptr; } else if (parent_) { // Is a live region root if this or an ancestor is a live region. - cached_live_region_root_ = IsLiveRegionRoot() ? const_cast<AXObject*>(this) - : parent_->LiveRegionRoot(); + cached_live_region_root_ = + IsLiveRegionRoot() ? this : parent_->LiveRegionRoot(); } if (cached_live_region_root_ != previous_live_region_root) { is_changing_inherited_values = true; @@ -3360,7 +3380,7 @@ #endif } -void AXObject::OnInheritedCachedValuesChanged() const { +void AXObject::OnInheritedCachedValuesChanged() { // When a cached value that can inherit its value changes, it means that // all descendants need to recompute its value. We do this by ensuring // that UpdateTreeIfNeeded() will visit all descendants and recompute @@ -3394,24 +3414,21 @@ // Ensure that all children of this node will be updated during the next // tree update in AXObjectCacheImpl::UpdateTreeIfNeeded(). SetNeedsToUpdateChildren(); - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { // Make sure that, starting at an included node, children will // recursively be updated until we reach |this|. - AXObjectCache().ChildrenChangedOnAncestorOf(const_cast<AXObject*>(this)); + AXObjectCache().ChildrenChangedOnAncestorOf(this); } } } -bool AXObject::ComputeAccessibilityIsIgnored( +bool AXObject::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { return ShouldIgnoreForHiddenOrInert(ignored_reasons); } bool AXObject::ShouldIgnoreForHiddenOrInert( IgnoredReasons* ignored_reasons) const { - // TODO(crbug.com/1522716): Figure out how this can happen: - // "Check failed: !cached_values_need_update_. Tried to compute ignored value - // without up-to-date hidden/inert values on SELECT". DUMP_WILL_BE_CHECK(!cached_values_need_update_) << "Tried to compute ignored value without up-to-date hidden/inert " "values on " @@ -3471,7 +3488,7 @@ // Note: do not rely on the value of this inside of display:none. // In practice, it does not matter because nodes in display:none subtrees are // marked ignored either way. -bool AXObject::IsInert() const { +bool AXObject::IsInert() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); @@ -3573,7 +3590,7 @@ return ComputeIsInertViaStyle(GetComputedStyle(), ignored_reasons); } -bool AXObject::IsAriaHidden() const { +bool AXObject::IsAriaHidden() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); @@ -3612,14 +3629,13 @@ return false; } -bool AXObject::IsHiddenByChildTree() const { +bool AXObject::IsHiddenByChildTree() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); return cached_is_hidden_by_child_tree_; } -bool AXObject::ComputeIsHiddenByChildTree( - IgnoredReasons* ignored_reasons) const { +bool AXObject::ComputeIsHiddenByChildTree(IgnoredReasons* ignored_reasons) { const AXObject* parent = ParentObject(); if (!parent) { return false; @@ -3796,14 +3812,14 @@ return false; } -bool AXObject::IsDescendantOfDisabledNode() const { +bool AXObject::IsDescendantOfDisabledNode() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); return cached_is_descendant_of_disabled_node_; } -bool AXObject::ComputeIsDescendantOfDisabledNode() const { +bool AXObject::ComputeIsDescendantOfDisabledNode() { if (IsA<Document>(GetNode())) return false; @@ -3884,7 +3900,7 @@ return true; } -bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const { +bool AXObject::ComputeIsIgnoredButIncludedInTree() { // If an inline text box is ignored, it is never included in the tree. if (IsAXInlineTextBox()) { return false; @@ -4168,24 +4184,6 @@ return AXObjectCache().Get(input); } -bool AXObject::LastKnownIsIgnoredValue() const { - DCHECK(cached_is_ignored_ || !IsDetached()) - << "A detached object should always indicate that it is ignored so that " - "it won't ever accidentally be included in the tree."; - return cached_is_ignored_; -} - -bool AXObject::LastKnownIsIgnoredButIncludedInTreeValue() const { - DCHECK(!cached_is_ignored_but_included_in_tree_ || !IsDetached()) - << "A detached object should never be included in the tree."; - return cached_is_ignored_but_included_in_tree_; -} - -bool AXObject::LastKnownIsIncludedInTreeValue() const { - return !LastKnownIsIgnoredValue() || - LastKnownIsIgnoredButIncludedInTreeValue(); -} - ax::mojom::blink::Role AXObject::DetermineRoleValue() { #if DCHECK_IS_ON() base::AutoReset<bool> reentrancy_protector(&is_computing_role_, true); @@ -4223,7 +4221,7 @@ } } -bool AXObject::CanSetFocusAttribute() const { +bool AXObject::CanSetFocusAttribute() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); @@ -4235,7 +4233,7 @@ // returning early if IsHiddenViaStyle() is true, we can call // Element::IsKeyboardFocusable(), which would otherwise recalculate style at an // awkward time. -bool AXObject::ComputeCanSetFocusAttribute() const { +bool AXObject::ComputeCanSetFocusAttribute() { DCHECK(!IsDetached()); DCHECK(GetDocument()); @@ -4535,7 +4533,7 @@ // work, but don't destroy the work that was already there" // * "content-visibility: auto" is "paint when it's scrolled into the viewport, // but its layout information is not updated when it isn't" -bool AXObject::ComputeIsHiddenViaStyle(const ComputedStyle* style) const { +bool AXObject::ComputeIsHiddenViaStyle(const ComputedStyle* style) { // The the parent element of text is hidden, then the text is hidden too. // This helps provide more consistent results in edge cases, e.g. text inside // of a <canvas> or display:none content. @@ -4583,7 +4581,7 @@ return node->IsElementNode(); } -bool AXObject::IsHiddenViaStyle() const { +bool AXObject::IsHiddenViaStyle() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); @@ -4662,12 +4660,12 @@ return IsHiddenViaStyle(); } -bool AXObject::IsUsedForLabelOrDescription() const { +bool AXObject::IsUsedForLabelOrDescription() { UpdateCachedAttributeValuesIfNeeded(); return cached_is_used_for_label_or_description_; } -bool AXObject::ComputeIsUsedForLabelOrDescription() const { +bool AXObject::ComputeIsUsedForLabelOrDescription() { if (GetElement()) { // Return true if a <label> or the target of a naming/description // relation (<aria-labelledby or aria-describedby). @@ -4681,7 +4679,7 @@ // contents as a repair. // Note: this must match the SupportsNameFromContents() rule in // AXRelationCache::UpdateRelatedText(). - if ((!AccessibilityIsIgnored() || CanSetFocusAttribute()) && + if ((!IsIgnored() || CanSetFocusAttribute()) && SupportsNameFromContents(/*recursive*/ false)) { // Descendants of nodes that label themselves via their inner contents // and are visible are effectively part of the label for that node. @@ -4846,7 +4844,7 @@ HeapHashSet<Member<AXObject>> children; // If the current object is included, check its children. - if (obj->AccessibilityIsIncludedInTree()) { + if (obj->IsIncludedInTree()) { for (const auto& child : obj->ChildrenIncludingIgnored()) { children.insert(child); } @@ -5209,7 +5207,7 @@ } int AXObject::IndexInParent() const { - DCHECK(AccessibilityIsIncludedInTree()) + DCHECK(IsIncludedInTree()) << "IndexInParent is only valid when a node is included in the tree"; AXObject* ax_parent_included = ParentObjectIncludedInTree(); if (!ax_parent_included) @@ -5228,7 +5226,7 @@ } bool AXObject::IsOnlyChild() const { - DCHECK(AccessibilityIsIncludedInTree()) + DCHECK(IsIncludedInTree()) << "IsOnlyChild is only valid when a node is included in the tree"; AXObject* ax_parent_included = ParentObjectIncludedInTree(); if (!ax_parent_included) { @@ -5484,11 +5482,11 @@ return node->IsRichlyEditableForAccessibility(); } -AXObject* AXObject::LiveRegionRoot() const { +AXObject* AXObject::LiveRegionRoot() { CheckCanAccessCachedValues(); UpdateCachedAttributeValuesIfNeeded(); - return cached_live_region_root_.Get(); + return cached_live_region_root_; } bool AXObject::LiveRegionAtomic() const { @@ -5503,34 +5501,22 @@ } const AtomicString& AXObject::ContainerLiveRegionStatus() const { - CheckCanAccessCachedValues(); - - UpdateCachedAttributeValuesIfNeeded(); return cached_live_region_root_ ? cached_live_region_root_->LiveRegionStatus() : g_null_atom; } const AtomicString& AXObject::ContainerLiveRegionRelevant() const { - CheckCanAccessCachedValues(); - - UpdateCachedAttributeValuesIfNeeded(); return cached_live_region_root_ ? cached_live_region_root_->LiveRegionRelevant() : g_null_atom; } bool AXObject::ContainerLiveRegionAtomic() const { - CheckCanAccessCachedValues(); - - UpdateCachedAttributeValuesIfNeeded(); return cached_live_region_root_ && cached_live_region_root_->LiveRegionAtomic(); } bool AXObject::ContainerLiveRegionBusy() const { - CheckCanAccessCachedValues(); - - UpdateCachedAttributeValuesIfNeeded(); return cached_live_region_root_ && cached_live_region_root_->AOMPropertyOrARIAAttributeIsTrue( AOMBooleanProperty::kBusy); @@ -5574,7 +5560,7 @@ const AXObject::AXObjectVector& AXObject::ChildrenIncludingIgnored() const { DCHECK(!IsDetached()); - return const_cast<AXObject*>(this)->ChildrenIncludingIgnored(); + return children_; } const AXObject::AXObjectVector& AXObject::ChildrenIncludingIgnored() { @@ -5589,7 +5575,7 @@ const AXObject::AXObjectVector AXObject::UnignoredChildren() { UpdateChildrenIfNecessary(); - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support finding the unignored children of " "objects excluded from the accessibility tree: " << this; @@ -5618,7 +5604,7 @@ AXObjectVector unignored_children; AXObject* child = FirstChildIncludingIgnored(); while (child && child != this) { - if (child->AccessibilityIsIgnored()) { + if (child->IsIgnored()) { child = child->NextInPreOrderIncludingIgnored(this); continue; } @@ -5677,7 +5663,7 @@ } AXObject* AXObject::NextSiblingIncludingIgnored() const { - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support iterating children of objects excluded " "from the accessibility tree: " << this; @@ -5695,7 +5681,7 @@ } AXObject* AXObject::PreviousSiblingIncludingIgnored() const { - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support iterating children of objects excluded " "from the accessibility tree: " << this; @@ -5713,7 +5699,7 @@ } AXObject* AXObject::CachedPreviousSiblingIncludingIgnored() const { - if (!LastKnownIsIncludedInTreeValue()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support iterating children of objects excluded " "from the accessibility tree: " << this; @@ -5738,9 +5724,9 @@ AXObject* AXObject::NextInPreOrderIncludingIgnored( const AXObject* within) const { - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { // TODO(crbug.com/1421052): Make sure this no longer fires then turn the - // above into CHECK(AccessibilityIsIncludedInTree()); + // above into CHECK(IsIncludedInTree()); DUMP_WILL_BE_NOTREACHED_NORETURN() << "We don't support iterating children of objects excluded " "from the accessibility tree: " @@ -5766,7 +5752,7 @@ AXObject* AXObject::PreviousInPreOrderIncludingIgnored( const AXObject* within) const { - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support iterating children of objects excluded " "from the accessibility tree: " << this; @@ -5786,7 +5772,7 @@ AXObject* AXObject::PreviousInPostOrderIncludingIgnored( const AXObject* within) const { - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { NOTREACHED() << "We don't support iterating children of objects excluded " "from the accessibility tree: " << this; @@ -5821,9 +5807,9 @@ } AXObject* AXObject::UnignoredNextSibling() const { - if (AccessibilityIsIgnored()) { + if (IsIgnored()) { // TODO(crbug.com/1407397): Make sure this no longer fires then turn this - // block into CHECK(!AccessibilityIsIgnored()); + // block into CHECK(!IsIgnored()); DUMP_WILL_BE_NOTREACHED_NORETURN() << "We don't support finding unignored siblings for ignored " "objects because it is not clear whether to search for the " @@ -5850,7 +5836,7 @@ if (sibling) { // If we found an ignored sibling, walk in next pre-order // until an unignored object is found, flattening the ignored object. - while (sibling && sibling->AccessibilityIsIgnored()) { + while (sibling && sibling->IsIgnored()) { sibling = sibling->NextInPreOrderIncludingIgnored(unignored_parent); } return sibling; @@ -5859,14 +5845,14 @@ // If a sibling has not been found, try again with the parent object, // until the unignored parent is reached. current_obj = current_obj->ParentObjectIncludedInTree(); - if (!current_obj || !current_obj->AccessibilityIsIgnored()) + if (!current_obj || !current_obj->IsIgnored()) return nullptr; } return nullptr; } AXObject* AXObject::UnignoredPreviousSibling() const { - if (AccessibilityIsIgnored()) { + if (IsIgnored()) { NOTREACHED() << "We don't support finding unignored siblings for ignored " "objects because it is not clear whether to search for the " "sibling in the unignored tree or in the whole tree: " @@ -5892,7 +5878,7 @@ const AXObject* unignored_parent = ParentObjectUnignored(); // If we found an ignored sibling, walk in previous post-order // until an unignored object is found, flattening the ignored object. - while (sibling && sibling->AccessibilityIsIgnored()) { + while (sibling && sibling->IsIgnored()) { sibling = sibling->PreviousInPostOrderIncludingIgnored(unignored_parent); } @@ -5902,7 +5888,7 @@ // If a sibling has not been found, try again with the parent object, // until the unignored parent is reached. current_obj = current_obj->ParentObjectIncludedInTree(); - if (!current_obj || !current_obj->AccessibilityIsIgnored()) + if (!current_obj || !current_obj->IsIgnored()) return nullptr; } return nullptr; @@ -5910,7 +5896,7 @@ AXObject* AXObject::UnignoredNextInPreOrder() const { AXObject* next = NextInPreOrderIncludingIgnored(); - while (next && next->AccessibilityIsIgnored()) { + while (next && next->IsIgnored()) { next = next->NextInPreOrderIncludingIgnored(); } return next; @@ -5918,25 +5904,21 @@ AXObject* AXObject::UnignoredPreviousInPreOrder() const { AXObject* previous = PreviousInPreOrderIncludingIgnored(); - while (previous && previous->AccessibilityIsIgnored()) { + while (previous && previous->IsIgnored()) { previous = previous->PreviousInPreOrderIncludingIgnored(); } return previous; } AXObject* AXObject::ParentObject() const { - if (IsDetached()) { - return nullptr; - } - + DUMP_WILL_BE_CHECK(!IsDetached()); DUMP_WILL_BE_CHECK(!IsMissingParent()) << "Missing parent: " << this; - - return parent_.Get(); + return parent_; } AXObject* AXObject::ParentObjectUnignored() const { AXObject* parent; - for (parent = ParentObject(); parent && parent->AccessibilityIsIgnored(); + for (parent = ParentObject(); parent && parent->IsIgnored(); parent = parent->ParentObject()) { } @@ -5946,7 +5928,7 @@ AXObject* AXObject::ParentObjectIncludedInTree() const { AXObject* parent; for (parent = ParentObject(); - parent && !parent->AccessibilityIsIncludedInTree(); + parent && !parent->IsIncludedInTree(); parent = parent->ParentObject()) { } @@ -6068,7 +6050,7 @@ #if DCHECK_IS_ON() void AXObject::CheckIncludedObjectConnectedToRoot() const { - if (!LastKnownIsIncludedInTreeValue() || IsRoot()) { + if (!IsIncludedInTree() || IsRoot()) { return; } @@ -6077,7 +6059,7 @@ const AXObject* included_parent = nullptr; for (ancestor = CachedParentObject(); ancestor; ancestor = ancestor->CachedParentObject()) { - if (ancestor->LastKnownIsIncludedInTreeValue()) { + if (ancestor->IsIncludedInTree()) { included_parent = ancestor; if (included_parent->CachedChildrenIncludingIgnored().Find( included_child) == kNotFound) { @@ -6104,7 +6086,7 @@ } #endif -void AXObject::SetNeedsToUpdateChildren(bool update) const { +void AXObject::SetNeedsToUpdateChildren(bool update) { CHECK(!IsDetached()) << "Cannot update children on a detached node: " << this; CHECK(!AXObjectCache().IsFrozen()); CHECK(!AXObjectCache().HasBeenDisposed()); @@ -6213,7 +6195,7 @@ AXObjectCache().UpdateAXForAllDocuments(); } -void AXObject::ClearChildren() const { +void AXObject::ClearChildren() { CHECK(!IsDetached()); CHECK(!AXObjectCache().IsFrozen()) << "Do not clear children while tree is frozen: " << this; @@ -6340,7 +6322,7 @@ // no longer be ignored. This is rare, but is covered by this test: // external/wpt/accessibility/crashtests/delayed-ignored-change.html/ // In this case, first ancestor that's still included in the tree will used. - if (!LastKnownIsIncludedInTreeValue()) { + if (!IsIncludedInTree()) { if (AXObject* ax_parent = CachedParentObject()) { ax_parent->ChildrenChangedWithCleanLayout(); return; @@ -7937,11 +7919,11 @@ } // Extra checks that only occur during serialization. -void AXObject::PreSerializationConsistencyCheck() { +void AXObject::PreSerializationConsistencyCheck() const{ CHECK(!IsDetached()) << "Do not serialize detached nodes: " << this; CHECK(AXObjectCache().IsFrozen()); CHECK(!NeedsToUpdateCachedValues()) << "Stale values on: " << this; - if (!AccessibilityIsIncludedInTree()) { + if (!IsIncludedInTree()) { AXObject* included_parent = ParentObjectIncludedInTree(); // TODO(accessibility): Return to CHECK once it has been resolved, // so that the message does not bloat stable releases. @@ -8046,8 +8028,7 @@ } if (!IsDetached() && AXObjectCache().IsAriaOwned(this)) string_builder = string_builder + " isAriaOwned"; - if (cached_values_only ? LastKnownIsIgnoredValue() - : AccessibilityIsIgnored()) { + if (IsIgnored()) { string_builder = string_builder + " isIgnored"; #if defined(AX_FAIL_FAST_BUILD) // TODO(accessibility) Move this out of AX_FAIL_FAST_BUILD by having a new @@ -8056,13 +8037,13 @@ // inspector_type_builder_helper.cc. if (!cached_values_only && !IsDetached()) { AXObject::IgnoredReasons reasons; - ComputeAccessibilityIsIgnored(&reasons); + ComputeIsIgnored(&reasons); string_builder = string_builder + GetIgnoredReasonsDebugString(reasons); } #endif - if (cached_values_only ? !LastKnownIsIncludedInTreeValue() - : !AccessibilityIsIncludedInTree()) + if (!IsIncludedInTree()) { string_builder = string_builder + " isRemovedFromTree"; + } } if (GetNode()) { if (GetNode()->OwnerShadowHost()) { @@ -8122,9 +8103,9 @@ if (HasDirtyDescendants()) { string_builder = string_builder + " hasDirtyDescendants"; } - AXObject* included_parent = parent_; + const AXObject* included_parent = parent_; while (included_parent && - !included_parent->LastKnownIsIncludedInTreeValue()) { + !included_parent->IsIncludedInTree()) { included_parent = included_parent->CachedParentObject(); } if (included_parent) { @@ -8132,7 +8113,7 @@ string_builder = string_builder + " includedParentMissingHasDirtyDescendants"; } - if (LastKnownIsIncludedInTreeValue()) { + if (IsIncludedInTree()) { // All cached children must be included. const HeapVector<Member<AXObject>>& siblings = included_parent->CachedChildrenIncludingIgnored();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index f645375..9a0cf83 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -267,7 +267,7 @@ #if DCHECK_IS_ON() bool is_initializing_ = false; bool is_computing_role_ = false; - mutable bool is_updating_cached_values_ = false; + bool is_updating_cached_values_ = false; #endif #if !defined(NDEBUG) // Keep track of what the object used to be, to make it easier to debug @@ -306,8 +306,8 @@ // AXObjectCacheImpl::UpdateTreeIfNeeded. It does not directly indicate // whether children, parent or other pointers are actually out of date; there // are other dirty bits such as children_dirty_ for that. - void SetAncestorsHaveDirtyDescendants() const; - void SetHasDirtyDescendants(bool dirty) const; + void SetAncestorsHaveDirtyDescendants(); + void SetHasDirtyDescendants(bool dirty); bool HasDirtyDescendants() const { return has_dirty_descendants_; } // When the corresponding WebCore object that this AXObject @@ -322,7 +322,7 @@ // tree status changes. Use |notify_parent_of_ignored_changes = false| to // prevent this. void UpdateCachedAttributeValuesIfNeeded( - bool notify_parent_of_ignored_changes = true) const; + bool notify_parent_of_ignored_changes = true); // Invalidates cached_* members on this object only by resetting the // modification count. @@ -373,7 +373,7 @@ // // TODO(crbug.com/1068668): AX onion soup - finish migrating // BlinkAXTreeSource::SerializeNode into AXObject::Serialize. - void Serialize(ui::AXNodeData* node_data, ui::AXMode accessibility_mode); + void Serialize(ui::AXNodeData* node_data, ui::AXMode accessibility_mode) const; // Determine subclass type. virtual bool IsImageMapLink() const; @@ -500,16 +500,31 @@ bool CanSetValueAttribute() const; // Is the element focusable? - bool CanSetFocusAttribute() const; + bool CanSetFocusAttribute() const { return cached_can_set_focus_attribute_; } + bool CanSetFocusAttribute(); // Is the element in the tab order? bool IsKeyboardFocusable() const; + // Whether objects are included in the tree. Nodes that are included in the + // tree are serialized, even if they are ignored. This allows browser-side + // accessibility code to have a more accurate representation of the tree. e.g. + // inspect hidden nodes referenced by labeled-by, know where line breaking + // elements are, etc. + bool IsIncludedInTree() const; + bool IsIncludedInTree(); + bool CachedIsIncludedInTree(); + // Whether objects are ignored, i.e. hidden from the AT. - bool AccessibilityIsIgnored() const; - // Whether objects are ignored but included in the tree. - bool AccessibilityIsIgnoredButIncludedInTree() const; + bool IsIgnored() const; + bool IsIgnored(); + + // Whether an ignored object should still be included in the serialized tree. + bool IsIgnoredButIncludedInTree() const; + bool IsIgnoredButIncludedInTree(); + // Is visibility:hidden or display:none being used to hide this element. - bool IsHiddenViaStyle() const; + bool IsHiddenViaStyle() const { return cached_is_hidden_via_style_; } + bool IsHiddenViaStyle(); // Whether this is part of the label or description for another element. // This is used to ensure hidden objects are included in the tree, and the // implementation currently only ensures that an element's ancestor was part @@ -517,39 +532,35 @@ // the relation cache does not bother clear old aria-labelledby/describedby // ids. However, for purposes of preventing too many hidden objects from being // serialized, it works well. - bool IsUsedForLabelOrDescription() const; - bool CachedIsUsedForLabelOrDescription() const { + bool IsUsedForLabelOrDescription() const { return cached_is_used_for_label_or_description_; } + bool IsUsedForLabelOrDescription(); - // Whether objects are included in the tree. Nodes that are included in the - // tree are serialized, even if they are ignored. This allows browser-side - // accessibility code to have a more accurate representation of the tree. e.g. - // inspect hidden nodes referenced by labeled-by, know where line breaking - // elements are, etc. - bool AccessibilityIsIncludedInTree() const; typedef HeapVector<IgnoredReason> IgnoredReasons; - virtual bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const; + virtual bool ComputeIsIgnored(IgnoredReasons* = nullptr) const; bool ShouldIgnoreForHiddenOrInert(IgnoredReasons* = nullptr) const; - bool IsInert() const; - bool IsAriaHidden() const; - bool IsHiddenByChildTree() const; - bool CachedIsAriaHidden() { return cached_is_aria_hidden_; } + bool IsInert() const { return cached_is_inert_; } + bool IsInert(); + bool IsAriaHidden() const { return cached_is_aria_hidden_; } + bool IsAriaHidden(); + bool IsHiddenByChildTree() const { return cached_is_hidden_by_child_tree_; } + bool IsHiddenByChildTree(); const AXObject* AriaHiddenRoot() const; bool ComputeIsInert(IgnoredReasons* = nullptr) const; bool ComputeIsAriaHidden(IgnoredReasons* = nullptr) const; // Determines if the object is hidden because a child tree has been stitched // into one of its ancestor objects. - bool ComputeIsHiddenByChildTree(IgnoredReasons* = nullptr) const; + bool ComputeIsHiddenByChildTree(IgnoredReasons* = nullptr); bool IsBlockedByAriaModalDialog(IgnoredReasons* = nullptr) const; - bool IsDescendantOfDisabledNode() const; - bool ComputeAccessibilityIsIgnoredButIncludedInTree() const; + bool IsDescendantOfDisabledNode() const { + return cached_is_descendant_of_disabled_node_; + } + bool IsDescendantOfDisabledNode(); + bool ComputeIsIgnoredButIncludedInTree(); const AXObject* GetAtomicTextFieldAncestor(int max_levels_to_check = 3) const; const AXObject* DatetimeAncestor() const; - bool ComputeIsDescendantOfDisabledNode() const; - bool LastKnownIsIgnoredValue() const; - bool LastKnownIsIgnoredButIncludedInTreeValue() const; - bool LastKnownIsIncludedInTreeValue() const; + bool ComputeIsDescendantOfDisabledNode(); // Some objects, such as table header containers, could be the children of // more than one object but have only one primary parent. bool HasIndirectChildren() const; @@ -883,11 +894,11 @@ // Get the role to be used in StringAttribute::kRole, which is used in the // xml-roles object attribute. - const AtomicString& GetRoleStringForSerialization(ui::AXNodeData* node_data); + const AtomicString& GetRoleStringForSerialization(ui::AXNodeData* node_data) const; // ARIA attributes. bool HasAriaAttribute(bool does_undo_role_presentation = false) const; - virtual AXObject* ActiveDescendant() { return nullptr; } + virtual AXObject* ActiveDescendant() const { return nullptr; } virtual String AutoComplete() const { return String(); } virtual void AriaOwnsElements(AXObjectVector& owns) const {} virtual void AriaDescribedbyElements(AXObjectVector&) const {} @@ -911,7 +922,7 @@ AXObject* GetTargetPopoverForInvoker() const; // Heuristic to get the listbox for an <input role="combobox">. - AXObject* GetControlsListboxForTextfieldCombobox(); + AXObject* GetControlsListboxForTextfieldCombobox() const; // Returns true if this object is within or at the root of an editable region, // such as a contenteditable. Also, returns true if this object is an atomic @@ -967,7 +978,9 @@ // ARIA live-region features. bool IsLiveRegionRoot() const; // Any live region, including polite="off". bool IsActiveLiveRegionRoot() const; // Live region that is not polite="off". - AXObject* LiveRegionRoot() const; // Container that controls live politeness. + // Containing element that controls aria-live properties. + AXObject* LiveRegionRoot() const { return cached_live_region_root_; } + AXObject* LiveRegionRoot(); virtual const AtomicString& LiveRegionStatus() const; virtual const AtomicString& LiveRegionRelevant() const; bool LiveRegionAtomic() const; @@ -1184,7 +1197,7 @@ // Sets the parent AXObject directly. If the parent of this object is known, // this can be faster than using ComputeParent(). - void SetParent(AXObject* new_parent) const; + void SetParent(AXObject* new_parent); // If parent was not initialized during AddChildren() it can be computed by // walking the DOM (or layout for nodeless aka anonymous layout object). @@ -1294,8 +1307,8 @@ virtual bool CanHaveChildren() const { return true; } void UpdateChildrenIfNecessary(); bool NeedsToUpdateChildren() const; - virtual void SetNeedsToUpdateChildren(bool update = true) const; - virtual void ClearChildren() const; + virtual void SetNeedsToUpdateChildren(bool update = true); + virtual void ClearChildren(); void DetachFromParent(); virtual void SelectedOptions(AXObjectVector&) const {} @@ -1447,7 +1460,7 @@ const AXObject* aria_label_or_description_root) const; // Extra checks that occur right before a node is evaluated for serialization. - void PreSerializationConsistencyCheck(); + void PreSerializationConsistencyCheck() const; // Returns a string representation of this object. String ToString(bool verbose = true) const; @@ -1458,10 +1471,10 @@ protected: AXID id_; // Any parent, regardless of whether it's ignored or not included in the tree. - mutable Member<AXObject> parent_; + Member<AXObject> parent_; // Only children that are included in tree, maybe rename to children_in_tree_. - mutable AXObjectVector children_; - mutable bool has_dirty_descendants_ = false; + AXObjectVector children_; + bool has_dirty_descendants_ = false; // The final role, taking into account the ARIA role and native role. ax::mojom::blink::Role role_; @@ -1520,28 +1533,28 @@ // Helpers for serialization. void SerializeBoundingBoxAttributes(ui::AXNodeData& dst) const; - void SerializeActionAttributes(ui::AXNodeData* node_data); - void SerializeChildTreeID(ui::AXNodeData* node_data); - void SerializeChooserPopupAttributes(ui::AXNodeData* node_data); - void SerializeColorAttributes(ui::AXNodeData* node_data); - void SerializeElementAttributes(ui::AXNodeData* node_data); - void SerializeHTMLTagAndClass(ui::AXNodeData* node_data); - void SerializeHTMLAttributes(ui::AXNodeData* node_data); + void SerializeActionAttributes(ui::AXNodeData* node_data) const; + void SerializeChildTreeID(ui::AXNodeData* node_data) const; + void SerializeChooserPopupAttributes(ui::AXNodeData* node_data) const; + void SerializeColorAttributes(ui::AXNodeData* node_data) const; + void SerializeElementAttributes(ui::AXNodeData* node_data) const; + void SerializeHTMLTagAndClass(ui::AXNodeData* node_data) const; + void SerializeHTMLAttributes(ui::AXNodeData* node_data) const; void SerializeInlineTextBoxAttributes(ui::AXNodeData* node_data) const; - void SerializeLangAttribute(ui::AXNodeData* node_data); - void SerializeListAttributes(ui::AXNodeData* node_data); + void SerializeLangAttribute(ui::AXNodeData* node_data) const; + void SerializeListAttributes(ui::AXNodeData* node_data) const; void SerializeListMarkerAttributes(ui::AXNodeData* dst) const; void SerializeLiveRegionAttributes(ui::AXNodeData* node_data) const; void SerializeNameAndDescriptionAttributes(ui::AXMode accessibility_mode, ui::AXNodeData* node_data) const; void SerializeOtherScreenReaderAttributes(ui::AXNodeData* node_data) const; - void SerializeScreenReaderAttributes(ui::AXNodeData* node_data); - void SerializeScrollAttributes(ui::AXNodeData* node_data); - void SerializeSparseAttributes(ui::AXNodeData* node_data); - void SerializeStyleAttributes(ui::AXNodeData* node_data); - void SerializeTableAttributes(ui::AXNodeData* node_data); + void SerializeScreenReaderAttributes(ui::AXNodeData* node_data) const; + void SerializeScrollAttributes(ui::AXNodeData* node_data) const; + void SerializeSparseAttributes(ui::AXNodeData* node_data) const; + void SerializeStyleAttributes(ui::AXNodeData* node_data) const; + void SerializeTableAttributes(ui::AXNodeData* node_data) const; void SerializeUnignoredAttributes(ui::AXNodeData* node_data, - ui::AXMode accessibility_mode); + ui::AXMode accessibility_mode) const; void SerializeComputedDetailsRelation(ui::AXNodeData* node_data) const; // Serialization implemented in specific subclasses. @@ -1552,17 +1565,17 @@ ui::AXNodeData* node_data) const; private: - bool ComputeCanSetFocusAttribute() const; + bool ComputeCanSetFocusAttribute(); String KeyboardShortcut() const; void UpdateStyleAndLayoutTreeForNode(Node& node); - void OnInheritedCachedValuesChanged() const; + void OnInheritedCachedValuesChanged(); - mutable bool children_dirty_ : 1 = false; + bool children_dirty_ : 1 = false; // Do the rest of the cached_* member variables need to be recomputed? - mutable bool cached_values_need_update_ : 1 = true; + bool cached_values_need_update_ : 1 = true; // Do children need to recompute their cached values? - mutable bool child_cached_values_need_update_ : 1 = false; + bool child_cached_values_need_update_ : 1 = false; // The following cached attribute values (the ones starting with cached_**) // are only valid if cached_values_need_update_ is false. @@ -1570,18 +1583,18 @@ // not included in the tree), so that if object becomes included in Init() // or in a future page update, the included node count will be incremented via // AXObjectCacheImpl::UpdateIncludedNodeCount(). - mutable bool cached_is_ignored_ : 1 = true; - mutable bool cached_is_ignored_but_included_in_tree_ : 1 = false; - mutable bool cached_is_inert_ : 1 = false; - mutable bool cached_is_aria_hidden_ : 1 = false; - mutable bool cached_is_hidden_by_child_tree_ : 1 = false; - mutable bool cached_is_hidden_via_style_ : 1 = false; - mutable bool cached_is_used_for_label_or_description_ : 1; - mutable bool cached_is_descendant_of_disabled_node_ : 1 = false; - mutable bool cached_can_set_focus_attribute_ : 1 = false; + bool cached_is_ignored_ : 1 = true; + bool cached_is_ignored_but_included_in_tree_ : 1 = false; + bool cached_is_inert_ : 1 = false; + bool cached_is_aria_hidden_ : 1 = false; + bool cached_is_hidden_by_child_tree_ : 1 = false; + bool cached_is_hidden_via_style_ : 1 = false; + bool cached_is_used_for_label_or_description_ : 1; + bool cached_is_descendant_of_disabled_node_ : 1 = false; + bool cached_can_set_focus_attribute_ : 1 = false; - mutable Member<AXObject> cached_live_region_root_; - mutable gfx::RectF cached_local_bounding_box_rect_for_accessibility_; + Member<AXObject> cached_live_region_root_; + gfx::RectF cached_local_bounding_box_rect_for_accessibility_; Member<AXObjectCacheImpl> ax_object_cache_; @@ -1593,8 +1606,8 @@ unsigned ComputeAriaColumnIndex() const; unsigned ComputeAriaRowIndex() const; const ComputedStyle* GetComputedStyle() const; - bool ComputeIsHiddenViaStyle(const ComputedStyle*) const; - bool ComputeIsUsedForLabelOrDescription() const; + bool ComputeIsHiddenViaStyle(const ComputedStyle*); + bool ComputeIsUsedForLabelOrDescription(); bool ComputeIsInertViaStyle(const ComputedStyle*, IgnoredReasons* = nullptr) const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 8aece3e9..f0fbce6b 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -839,7 +839,7 @@ void AXObjectCacheImpl::EnsureSerializer() { if (!ax_tree_serializer_) { ax_tree_serializer_ = std::make_unique<ui::AXTreeSerializer< - AXObject*, HeapVector<Member<AXObject>>, ui::AXTreeUpdate*, + const AXObject*, HeapVector<Member<const AXObject>>, ui::AXTreeUpdate*, ui::AXTreeData*, ui::AXNodeData>>(ax_tree_source_, /*crash_on_error*/ true); } @@ -932,7 +932,7 @@ // the HTML element, for example, is focusable but has an AX object that is // ignored - if (!obj->AccessibilityIsIncludedInTree()) + if (!obj->IsIncludedInTree()) obj = obj->ParentObjectIncludedInTree(); return obj; @@ -1541,7 +1541,7 @@ // Inline textboxes are included if and only if the parent is unignored. // If the parent is ignored but included in tree, the inline textbox is // still withheld. - if (parent->LastKnownIsIgnoredValue()) { + if (parent->IsIgnored()) { return nullptr; } @@ -1640,7 +1640,7 @@ return; #if DCHECK_IS_ON() - if (obj->LastKnownIsIncludedInTreeValue()) { + if (obj->CachedIsIncludedInTree()) { --included_node_count_; } #endif @@ -2315,7 +2315,7 @@ if (obj) { if (obj->RoleValue() == ax::mojom::blink::Role::kStaticText && - obj->AccessibilityIsIncludedInTree()) { + obj->IsIncludedInTree()) { if (obj->ShouldLoadInlineTextBoxes()) { // Update inline text box children. ChildrenChangedWithCleanLayout(optional_node_for_relation_update, obj); @@ -2726,7 +2726,7 @@ // Any ancestor up to the first included ancestor can contain the // now-detached child in it's cached children, and therefore must update // children. - if (ancestor->LastKnownIsIncludedInTreeValue()) { + if (ancestor->CachedIsIncludedInTree()) { break; } @@ -2742,7 +2742,7 @@ return nullptr; // Return ancestor to fire children changed notification on. - DCHECK(ancestor->LastKnownIsIncludedInTreeValue()) + DCHECK(ancestor->CachedIsIncludedInTree()) << "ChildrenChanged() must only be called on included nodes: " << ancestor; @@ -2947,10 +2947,10 @@ DCHECK(!object->ChildrenNeedToUpdateCachedValues()) << "Cached values for children should not require an update: " << "\n* Object: " << object; - if (object->AccessibilityIsIncludedInTree()) { + if (object->IsIncludedInTree()) { // All cached children must be included. for (const auto& child : object->CachedChildrenIncludingIgnored()) { - CHECK(child->AccessibilityIsIncludedInTree()) + CHECK(child->IsIncludedInTree()) << "Included parent cannot have unincluded child:" << "\n* Parent: " << object << "\n* Child: " << child; } @@ -4901,7 +4901,7 @@ } MarkAXObjectDirtyWithCleanLayoutHelper(obj, active_event_from_, active_event_from_action_); - if (!obj->AccessibilityIsIncludedInTree()) { + if (!obj->IsIncludedInTree()) { obj = obj->ParentObjectIncludedInTree(); } for (auto agent : agents_) { @@ -4920,7 +4920,7 @@ } void AXObjectCacheImpl::NotifySubtreeDirty(AXObject* obj) { - DUMP_WILL_BE_CHECK(obj->AccessibilityIsIncludedInTree()); + DUMP_WILL_BE_CHECK(obj->IsIncludedInTree()); // Note: if there is no serializer yet, then there is nothing to mark dirty // for serialization purposes yet -- effectively everything starts out dirty @@ -4937,7 +4937,7 @@ if (!obj) { return; } - if (!obj->AccessibilityIsIncludedInTree()) { + if (!obj->IsIncludedInTree()) { for (const auto& included_child : obj->ChildrenIncludingIgnored()) { MarkAXSubtreeDirtyWithCleanLayout(included_child); } @@ -5060,7 +5060,7 @@ } // Return included in tree object. - if (obj->AccessibilityIsIncludedInTree()) + if (obj->IsIncludedInTree()) return obj; return obj->ParentObjectIncludedInTree(); @@ -5235,7 +5235,7 @@ // or a partial accessibility tree. AXTreeSerializer is stateful, but the // first time you serialize from a brand-new tree you're guaranteed to get a // complete tree. - ui::AXTreeSerializer<AXObject*, HeapVector<Member<AXObject>>, + ui::AXTreeSerializer<const AXObject*, HeapVector<Member<const AXObject>>, ui::AXTreeUpdate*, ui::AXTreeData*, ui::AXNodeData> serializer(tree_source); @@ -5260,14 +5260,14 @@ } void AXObjectCacheImpl::AddDirtyObjectToSerializationQueue( - AXObject* obj, + const AXObject* obj, ax::mojom::blink::EventFrom event_from, ax::mojom::blink::Action event_from_action, const std::vector<ui::AXEventIntent>& event_intents) { CHECK(!IsFrozen()); // If not included, cannot be serialized, so there is no need to queue. - if (!obj->LastKnownIsIncludedInTreeValue()) { + if (!obj->IsIncludedInTree()) { return; } @@ -5313,7 +5313,7 @@ } ui::AXNodeData::AXNodeDataSize node_data_size; for (auto& current_dirty_object : dirty_objects_) { - AXObject* obj = current_dirty_object->obj; + const AXObject* obj = current_dirty_object->obj; // Dirty objects can be added using MarkWebAXObjectDirty(obj) from other // parts of the code as well, so we need to ensure the object still @@ -5333,7 +5333,7 @@ // cas a children changed will also be fired on the included ancestor. The // children changed event on the ancestor means that attempting to // serialize this unincluded object is not necessary. - if (!obj->AccessibilityIsIncludedInTree()) + if (!obj->IsIncludedInTree()) continue; DCHECK(obj->AXObjectID()); @@ -5447,7 +5447,7 @@ #if DCHECK_IS_ON() void AXObjectCacheImpl::UpdateIncludedNodeCount(const AXObject* obj) { - if (obj->LastKnownIsIncludedInTreeValue()) { + if (obj->IsIncludedInTree()) { ++included_node_count_; } else { --included_node_count_; @@ -5485,8 +5485,8 @@ std::vector<ui::AXNodeData*>& nodes) { for (auto& node : update.nodes) { AXObject* src = ObjectFromAXID(node.id); - if (!src || src->IsDetached() || !src->AccessibilityIsIncludedInTree() || - (src->AccessibilityIsIgnored() && + if (!src || src->IsDetached() || !src->IsIncludedInTree() || + (src->IsIgnored() && !node.HasState(ax::mojom::blink::State::kFocusable))) { continue; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h index f0ece41..7b494b3 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -513,13 +513,17 @@ std::set<ui::AXSerializationErrorFlag>* out_error = nullptr) override; // Marks an object as dirty to be serialized in the next serialization. + // If |subtree| is true, the entire subtree is dirty. + // |event_from| and |event_from_action| annotate this node change with info + // about the event which caused the change. For example, an event from a user + // or an event from a focus action. void AddDirtyObjectToSerializationQueue( - AXObject* obj, + const AXObject* obj, ax::mojom::blink::EventFrom event_from = ax::mojom::blink::EventFrom::kNone, ax::mojom::blink::Action event_from_action = ax::mojom::blink::Action::kNone, - const std::vector<ui::AXEventIntent>& event_intents = {}) override; + const std::vector<ui::AXEventIntent>& event_intents = {}); void GetUpdatesAndEventsForSerialization( std::vector<ui::AXTreeUpdate>& updates, @@ -649,7 +653,7 @@ private: struct AXDirtyObject : public GarbageCollected<AXDirtyObject> { - AXDirtyObject(AXObject* obj_arg, + AXDirtyObject(const AXObject* obj_arg, ax::mojom::blink::EventFrom event_from_arg, ax::mojom::blink::Action event_from_action_arg, std::vector<ui::AXEventIntent> event_intents_arg) @@ -658,7 +662,7 @@ event_from_action(event_from_action_arg), event_intents(event_intents_arg) {} - static AXDirtyObject* Create(AXObject* obj, + static AXDirtyObject* Create(const AXObject* obj, ax::mojom::blink::EventFrom event_from, ax::mojom::blink::Action event_from_action, std::vector<ui::AXEventIntent> event_intents) { @@ -668,7 +672,7 @@ void Trace(Visitor* visitor) const { visitor->Trace(obj); } - Member<AXObject> obj; + Member<const AXObject> obj; ax::mojom::blink::EventFrom event_from; ax::mojom::blink::Action event_from_action; std::vector<ui::AXEventIntent> event_intents ALLOW_DISCOURAGED_TYPE( @@ -1159,8 +1163,8 @@ render_accessibility_host_; Member<BlinkAXTreeSource> ax_tree_source_; - std::unique_ptr<ui::AXTreeSerializer<AXObject*, - HeapVector<Member<AXObject>>, + std::unique_ptr<ui::AXTreeSerializer<const AXObject*, + HeapVector<Member<const AXObject>>, ui::AXTreeUpdate*, ui::AXTreeData*, ui::AXNodeData>>
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc index ad1f51a..2564fb4 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
@@ -324,11 +324,11 @@ ASSERT_NE(nullptr, button); EXPECT_FALSE(button->IsDetached()); - EXPECT_FALSE(button->AccessibilityIsIgnored()); + EXPECT_FALSE(button->IsIgnored()); GetAXObjectCache().Remove(button->GetNode()); EXPECT_TRUE(button->IsDetached()); - EXPECT_TRUE(button->AccessibilityIsIgnored()); - EXPECT_FALSE(button->AccessibilityIsIgnoredButIncludedInTree()); + EXPECT_TRUE(button->IsIgnored()); + EXPECT_FALSE(button->IsIgnoredButIncludedInTree()); } TEST_F(AccessibilityTest, UnignoredChildren) { @@ -381,13 +381,13 @@ const AXObject* input = GetAXObjectByElementId("input"); ASSERT_NE(nullptr, input); ASSERT_NE(nullptr, GetAXObjectByElementId("ignored_a")); - ASSERT_TRUE(GetAXObjectByElementId("ignored_a")->AccessibilityIsIgnored()); + ASSERT_TRUE(GetAXObjectByElementId("ignored_a")->IsIgnored()); const AXObject* paragraph = GetAXObjectByElementId("paragraph"); ASSERT_NE(nullptr, paragraph); const AXObject* br = GetAXObjectByElementId("br"); ASSERT_NE(nullptr, br); ASSERT_NE(nullptr, GetAXObjectByElementId("ignored_b")); - ASSERT_TRUE(GetAXObjectByElementId("ignored_b")->AccessibilityIsIgnored()); + ASSERT_TRUE(GetAXObjectByElementId("ignored_b")->IsIgnored()); const AXObject* button = GetAXObjectByElementId("button"); ASSERT_NE(nullptr, button); @@ -485,7 +485,7 @@ const AXObject* span_1 = obj_a->ChildAtIncludingIgnored(0); ASSERT_NE(nullptr, span_1); EXPECT_EQ(ax::mojom::Role::kGenericContainer, span_1->RoleValue()); - EXPECT_TRUE(span_1->AccessibilityIsIgnoredButIncludedInTree()); + EXPECT_TRUE(span_1->IsIgnoredButIncludedInTree()); } TEST_F(AccessibilityTest, TreeNavigationWithIgnoredContainer) { @@ -509,29 +509,29 @@ ASSERT_EQ(3, body->ChildCountIncludingIgnored()); ASSERT_EQ(1, body->ChildAtIncludingIgnored(1)->ChildCountIncludingIgnored()); - ASSERT_FALSE(root->AccessibilityIsIgnored()); - ASSERT_TRUE(body->AccessibilityIsIgnored()); + ASSERT_FALSE(root->IsIgnored()); + ASSERT_TRUE(body->IsIgnored()); const AXObject* obj_a = GetAXObjectByElementId("A"); ASSERT_NE(nullptr, obj_a); - ASSERT_FALSE(obj_a->AccessibilityIsIgnored()); + ASSERT_FALSE(obj_a->IsIgnored()); const AXObject* obj_a_text = obj_a->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, obj_a_text); EXPECT_EQ(ax::mojom::Role::kStaticText, obj_a_text->RoleValue()); const AXObject* obj_b = GetAXObjectByElementId("B"); ASSERT_NE(nullptr, obj_b); - ASSERT_FALSE(obj_b->AccessibilityIsIgnored()); + ASSERT_FALSE(obj_b->IsIgnored()); const AXObject* obj_b_text = obj_b->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, obj_b_text); EXPECT_EQ(ax::mojom::Role::kStaticText, obj_b_text->RoleValue()); const AXObject* obj_c = GetAXObjectByElementId("C"); ASSERT_NE(nullptr, obj_c); - ASSERT_FALSE(obj_c->AccessibilityIsIgnored()); + ASSERT_FALSE(obj_c->IsIgnored()); const AXObject* obj_c_text = obj_c->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, obj_c_text); EXPECT_EQ(ax::mojom::Role::kStaticText, obj_c_text->RoleValue()); const AXObject* obj_ignored = body->ChildAtIncludingIgnored(1); ASSERT_NE(nullptr, obj_ignored); - ASSERT_TRUE(obj_ignored->AccessibilityIsIgnored()); + ASSERT_TRUE(obj_ignored->IsIgnored()); EXPECT_EQ(root, obj_a->ParentObjectUnignored()); EXPECT_EQ(body, obj_a->ParentObjectIncludedInTree()); @@ -611,7 +611,7 @@ const AXObject* ax_text_before = ax_link->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_text_before); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text_before->RoleValue()); - ASSERT_FALSE(ax_text_before->AccessibilityIsIgnored()); + ASSERT_FALSE(ax_text_before->IsIgnored()); const AXObject* ax_div = GetAXObjectByElementId("div"); ASSERT_NE(nullptr, ax_div); const AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); @@ -619,11 +619,11 @@ const AXObject* ax_text_inside = ax_paragraph->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_text_inside); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text_inside->RoleValue()); - ASSERT_FALSE(ax_text_inside->AccessibilityIsIgnored()); + ASSERT_FALSE(ax_text_inside->IsIgnored()); const AXObject* ax_text_after = ax_link->LastChildIncludingIgnored(); ASSERT_NE(nullptr, ax_text_after); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text_after->RoleValue()); - ASSERT_FALSE(ax_text_after->AccessibilityIsIgnored()); + ASSERT_FALSE(ax_text_after->IsIgnored()); // // Test parent / child relationships individually. This is easier to debug @@ -1661,32 +1661,6 @@ GetAXObjectByElementId("a-hidden-inert")->CanSetFocusAttribute()); } -TEST_F(AccessibilityTest, GetParentNodeForComputeParent) { - SetBodyInnerHTML( - R"HTML(<img usemap="#map"><map name="map"><area id="area" - shape="rect" coords="0,0,5,5" href="about:blank" alt="Area">)HTML"); - - AXObjectCacheImpl& cache = GetAXObjectCache(); - - // The parent of the area isn't the DOM parent, but the image because that - // mirrors the structure of the ax tree. - Element* area = GetElementById("area"); - AXObject* parent = AXObject::ComputeNonARIAParent(cache, area); - EXPECT_TRUE(IsA<HTMLImageElement>(parent->GetNode())); - - parent = AXObject::ComputeNonARIAParent(cache, parent->GetNode()); - EXPECT_TRUE(IsA<HTMLBodyElement>(parent->GetNode())); - - parent = AXObject::ComputeNonARIAParent(cache, parent->GetNode()); - EXPECT_TRUE(IsA<HTMLHtmlElement>(parent->GetNode())); - - parent = AXObject::ComputeNonARIAParent(cache, parent->GetNode()); - EXPECT_TRUE(IsA<Document>(parent->GetNode())); - - parent = AXObject::ComputeNonARIAParent(cache, parent->GetNode()); - EXPECT_EQ(parent, nullptr); -} - TEST_F(AccessibilityTest, CanComputeAsNaturalParent) { SetBodyInnerHTML(R"HTML(M<img usemap="#map"><map name="map"><hr><progress> <div><input type="range">M)HTML"); @@ -1747,19 +1721,19 @@ AXObject* ignored_button = GetAXObjectByElementId("ignoredButton"); ASSERT_NE(nullptr, ignored_button); - EXPECT_TRUE(div->AccessibilityIsIncludedInTree()); + EXPECT_TRUE(div->IsIncludedInTree()); EXPECT_TRUE(div->IsVisible()); EXPECT_EQ(1, div->ChildCountIncludingIgnored()); - EXPECT_TRUE(paragraph->AccessibilityIsIncludedInTree()); + EXPECT_TRUE(paragraph->IsIncludedInTree()); EXPECT_TRUE(paragraph->IsVisible()); - EXPECT_TRUE(paragraph_text->AccessibilityIsIncludedInTree()); + EXPECT_TRUE(paragraph_text->IsIncludedInTree()); EXPECT_TRUE(paragraph_text->IsVisible()); - EXPECT_TRUE(button->AccessibilityIsIgnored()); + EXPECT_TRUE(button->IsIgnored()); EXPECT_FALSE(button->IsVisible()); - EXPECT_TRUE(canvas->AccessibilityIsIgnored()); + EXPECT_TRUE(canvas->IsIgnored()); EXPECT_FALSE(canvas->IsVisible()); EXPECT_EQ(1, canvas->ChildCountIncludingIgnored()); - EXPECT_TRUE(ignored_button->AccessibilityIsIncludedInTree()); + EXPECT_TRUE(ignored_button->IsIncludedInTree()); EXPECT_FALSE(ignored_button->IsVisible()); EXPECT_FALSE(paragraph->IsHiddenByChildTree()); EXPECT_FALSE(paragraph_text->IsHiddenByChildTree()); @@ -1811,17 +1785,17 @@ canvas = GetAXObjectByElementId("canvas"); ASSERT_NE(nullptr, canvas); - EXPECT_TRUE(div->AccessibilityIsIncludedInTree()); + EXPECT_TRUE(div->IsIncludedInTree()); EXPECT_TRUE(div->IsVisible()); EXPECT_EQ(0, div->ChildCountIncludingIgnored()); - EXPECT_TRUE(button->AccessibilityIsIncludedInTree()) + EXPECT_TRUE(button->IsIncludedInTree()) << "`button` should switch from ignored due to `display:none`, to " "included in the tree."; EXPECT_FALSE(button->IsVisible()) << "The visibility state should not change, only the inclusion in the " "tree."; EXPECT_EQ(0, button->ChildCountIncludingIgnored()); - EXPECT_TRUE(canvas->AccessibilityIsIgnoredButIncludedInTree()); + EXPECT_TRUE(canvas->IsIgnoredButIncludedInTree()); EXPECT_FALSE(canvas->IsVisible()) << "The visibility state should not change, only the inclusion in the " "tree."; @@ -1832,10 +1806,10 @@ // once it walks the DOM tree again. EXPECT_TRUE(paragraph->IsHiddenByChildTree()); - EXPECT_TRUE(paragraph->AccessibilityIsIgnored()); + EXPECT_TRUE(paragraph->IsIgnored()); EXPECT_FALSE(paragraph->IsVisible()); EXPECT_TRUE(ignored_button->IsHiddenByChildTree()); - EXPECT_TRUE(ignored_button->AccessibilityIsIgnored()); + EXPECT_TRUE(ignored_button->IsIgnored()); EXPECT_FALSE(ignored_button->IsVisible()); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_position.cc b/third_party/blink/renderer/modules/accessibility/ax_position.cc index de44fa6..d1ad35d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_position.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_position.cc
@@ -25,7 +25,7 @@ const AXPosition AXPosition::CreatePositionBeforeObject( const AXObject& child, const AXPositionAdjustmentBehavior adjustment_behavior) { - if (child.IsDetached() || !child.AccessibilityIsIncludedInTree()) + if (child.IsDetached() || !child.IsIncludedInTree()) return {}; // If |child| is a text object, but not a text control, make behavior the same @@ -54,7 +54,7 @@ const AXPosition AXPosition::CreatePositionAfterObject( const AXObject& child, const AXPositionAdjustmentBehavior adjustment_behavior) { - if (child.IsDetached() || !child.AccessibilityIsIncludedInTree()) + if (child.IsDetached() || !child.IsIncludedInTree()) return {}; // If |child| is a text object, but not a text control, make behavior the same @@ -101,7 +101,7 @@ // invalid position, because child count is not always accurate for such // objects. const AXObject* unignored_container = - !container.AccessibilityIsIncludedInTree() + !container.IsIncludedInTree() ? container.ParentObjectIncludedInTree() : &container; DCHECK(unignored_container); @@ -136,7 +136,7 @@ // invalid position, because child count is not always accurate for such // objects. const AXObject* unignored_container = - !container.AccessibilityIsIncludedInTree() + !container.IsIncludedInTree() ? container.ParentObjectIncludedInTree() : &container; DCHECK(unignored_container); @@ -196,7 +196,7 @@ return {}; if (container_node->IsTextNode()) { - if (!container->AccessibilityIsIncludedInTree()) { + if (!container->IsIncludedInTree()) { // Find the closest DOM sibling that is unignored in the accessibility // tree. switch (adjustment_behavior) { @@ -292,7 +292,7 @@ } DCHECK(container_node->IsContainerNode()); - if (!container->AccessibilityIsIncludedInTree()) { + if (!container->IsIncludedInTree()) { container = container->ParentObjectIncludedInTree(); if (!container) return {}; @@ -315,7 +315,7 @@ // |ax_child| might be nullptr because not all DOM nodes can have AX // objects. For example, the "head" element has no corresponding AX // object. - if (!ax_child || !ax_child->AccessibilityIsIncludedInTree()) { + if (!ax_child || !ax_child->IsIncludedInTree()) { // Find the closest DOM sibling that is present and unignored in the // accessibility tree. switch (adjustment_behavior) { @@ -690,14 +690,14 @@ // Case 1. // Neither text positions nor "after children" positions have a |child| // object. - if (!container->AccessibilityIsIncludedInTree() && child) { + if (!container->IsIncludedInTree() && child) { // |CreatePositionBeforeObject| already finds the unignored parent before // creating the new position, so we don't need to replicate the logic here. return CreatePositionBeforeObject(*child, adjustment_behavior); } // Cases 2 and 3. - if (!container->AccessibilityIsIncludedInTree()) { + if (!container->IsIncludedInTree()) { // Case 2. if (IsTextPosition()) { if (!container->ParentObjectIncludedInTree()) @@ -728,7 +728,7 @@ } // Case 4. - if (child && !child->AccessibilityIsIncludedInTree()) { + if (child && !child->IsIncludedInTree()) { switch (adjustment_behavior) { case AXPositionAdjustmentBehavior::kMoveRight: return CreateLastPositionInObject(*container); @@ -1076,7 +1076,7 @@ while ((next_node = NodeTraversal::NextIncludingPseudo(*next_node, container_node))) { const AXObject* next_object = ax_object_cache_impl->Get(next_node); - if (next_object && next_object->AccessibilityIsIncludedInTree()) + if (next_object && next_object->IsIncludedInTree()) return next_object; } return nullptr; @@ -1094,7 +1094,7 @@ previous_node != container_node) { const AXObject* previous_object = ax_object_cache_impl->Get(previous_node); - if (previous_object && previous_object->AccessibilityIsIncludedInTree()) + if (previous_object && previous_object->IsIncludedInTree()) return previous_object; } return nullptr;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc index fc1f695..f1f7a57 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
@@ -867,7 +867,7 @@ const AXObject* ax_label = GetAXObjectByElementId("label"); ASSERT_NE(nullptr, ax_label); - ASSERT_FALSE(ax_label->AccessibilityIsIgnored()); + ASSERT_FALSE(ax_label->IsIgnored()); const AXObject* ax_label_text = ax_label->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_label_text); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_label_text->RoleValue()); @@ -942,10 +942,10 @@ // The HTML label element should be ignored. const AXObject* ax_label = GetAXObjectByElementId("label"); ASSERT_NE(nullptr, ax_label); - ASSERT_TRUE(ax_label->AccessibilityIsIgnored()); + ASSERT_TRUE(ax_label->IsIgnored()); const AXObject* ax_label_text = ax_label->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_label_text); - ASSERT_TRUE(ax_label_text->AccessibilityIsIgnored()); + ASSERT_TRUE(ax_label_text->IsIgnored()); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_label_text->RoleValue()); const AXObject* ax_paragraph = GetAXObjectByElementId("paragraph"); ASSERT_NE(nullptr, ax_paragraph); @@ -1044,7 +1044,7 @@ const AXObject* ax_hidden = GetAXObjectByElementId("hidden"); ASSERT_NE(nullptr, ax_hidden); ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_hidden->RoleValue()); - ASSERT_TRUE(ax_hidden->AccessibilityIsIgnoredButIncludedInTree()); + ASSERT_TRUE(ax_hidden->IsIgnoredButIncludedInTree()); const AXObject* ax_visible = GetAXObjectByElementId("visible"); ASSERT_NE(nullptr, ax_visible); @@ -1133,7 +1133,7 @@ ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue()); const AXObject* ax_hidden = GetAXObjectByElementId("ariaHidden"); ASSERT_NE(nullptr, ax_hidden); - ASSERT_TRUE(ax_hidden->AccessibilityIsIgnored()); + ASSERT_TRUE(ax_hidden->IsIgnored()); const auto ax_position = AXPosition::CreatePositionAfterObject(*ax_before); const auto position = ax_position.ToPositionWithAffinity(); @@ -1166,7 +1166,7 @@ ASSERT_NE(nullptr, ax_after); ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue()); ASSERT_NE(nullptr, GetAXObjectByElementId("ariaHidden")); - ASSERT_TRUE(GetAXObjectByElementId("ariaHidden")->AccessibilityIsIgnored()); + ASSERT_TRUE(GetAXObjectByElementId("ariaHidden")->IsIgnored()); const auto ax_position = AXPosition::CreatePositionBeforeObject(*ax_after); const auto position = ax_position.ToPositionWithAffinity(); @@ -1217,7 +1217,7 @@ ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue()); const AXObject* ax_hidden = GetAXObjectByElementId("ariaHidden"); ASSERT_NE(nullptr, ax_hidden); - ASSERT_TRUE(ax_hidden->AccessibilityIsIgnored()); + ASSERT_TRUE(ax_hidden->IsIgnored()); const auto position_first = Position::FirstPositionInNode(*hidden); // Since "ax_hidden" has a static text child, the AXPosition should move to an @@ -1520,7 +1520,7 @@ const AXObject* ax_quote = GetAXObjectByElementId("quote"); ASSERT_NE(nullptr, ax_quote); - ASSERT_TRUE(ax_quote->AccessibilityIsIgnored()); + ASSERT_TRUE(ax_quote->IsIgnored()); const AXObject* ax_quote_parent = ax_quote->ParentObjectUnignored(); ASSERT_NE(nullptr, ax_quote_parent); ASSERT_EQ(4, ax_quote_parent->UnignoredChildCount());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc index c958519..3b0500a2 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
@@ -724,10 +724,10 @@ // Owned children must be in tree to avoid serialization issues. for (AXObject* child : validated_owned_children_result) { DCHECK(IsAriaOwned(child)); - DCHECK(child->ComputeAccessibilityIsIgnoredButIncludedInTree()) + DCHECK(child->ComputeIsIgnoredButIncludedInTree()) << "Owned child not in tree: " << child << "\nRecompute included in tree: " - << child->ComputeAccessibilityIsIgnoredButIncludedInTree(); + << child->ComputeIsIgnoredButIncludedInTree(); } #endif @@ -892,7 +892,7 @@ GetReverseRelated(current_node, id_attr_to_text_relation_mapping_, related_sources); for (AXObject* related : related_sources) { - if (related && related->LastKnownIsIncludedInTreeValue() && + if (related && related->IsIncludedInTree() && !related->NeedsToUpdateChildren()) { object_cache_->MarkAXObjectDirtyWithCleanLayout(related); } @@ -903,7 +903,7 @@ if (current_node != node) { AXObject* obj = Get(current_node); if (obj && - (!obj->LastKnownIsIgnoredValue() || obj->CanSetFocusAttribute()) && + (!obj->IsIgnored() || obj->CanSetFocusAttribute()) && obj->SupportsNameFromContents(/*recursive=*/false) && !obj->NeedsToUpdateChildren()) { object_cache_->MarkAXObjectDirtyWithCleanLayout(obj);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc index 99134ef..dc546d65 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -527,26 +527,26 @@ const AXObject* ax_hidden1 = GetAXObjectByElementId("hidden1"); ASSERT_NE(nullptr, ax_hidden1); ASSERT_EQ(ax::mojom::Role::kParagraph, ax_hidden1->RoleValue()); - ASSERT_TRUE(ax_hidden1->AccessibilityIsIgnored()); - ASSERT_TRUE(ax_hidden1->AccessibilityIsIncludedInTree()); + ASSERT_TRUE(ax_hidden1->IsIgnored()); + ASSERT_TRUE(ax_hidden1->IsIncludedInTree()); const AXObject* ax_hidden1_text = ax_hidden1->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_hidden1_text); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_hidden1_text->RoleValue()); - ASSERT_TRUE(ax_hidden1_text->AccessibilityIsIgnored()); - ASSERT_TRUE(ax_hidden1_text->AccessibilityIsIncludedInTree()); + ASSERT_TRUE(ax_hidden1_text->IsIgnored()); + ASSERT_TRUE(ax_hidden1_text->IsIncludedInTree()); const AXObject* ax_between = GetAXObjectByElementId("betweenHidden"); ASSERT_NE(nullptr, ax_between); ASSERT_EQ(ax::mojom::Role::kParagraph, ax_between->RoleValue()); const AXObject* ax_hidden2 = GetAXObjectByElementId("hidden2"); ASSERT_NE(nullptr, ax_hidden2); ASSERT_EQ(ax::mojom::Role::kParagraph, ax_hidden2->RoleValue()); - ASSERT_TRUE(ax_hidden2->AccessibilityIsIgnored()); - ASSERT_TRUE(ax_hidden2->AccessibilityIsIncludedInTree()); + ASSERT_TRUE(ax_hidden2->IsIgnored()); + ASSERT_TRUE(ax_hidden2->IsIncludedInTree()); const AXObject* ax_hidden2_text = ax_hidden2->FirstChildIncludingIgnored(); ASSERT_NE(nullptr, ax_hidden2_text); ASSERT_EQ(ax::mojom::Role::kStaticText, ax_hidden2_text->RoleValue()); - ASSERT_TRUE(ax_hidden2_text->AccessibilityIsIgnored()); - ASSERT_TRUE(ax_hidden2_text->AccessibilityIsIncludedInTree()); + ASSERT_TRUE(ax_hidden2_text->IsIgnored()); + ASSERT_TRUE(ax_hidden2_text->IsIncludedInTree()); const AXObject* ax_after = GetAXObjectByElementId("afterHidden"); ASSERT_NE(nullptr, ax_after); ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc index 21729db3..471e16d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
@@ -13,14 +13,14 @@ namespace blink { void SetIntAttribute(ax::mojom::blink::IntAttribute attribute, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { node_data->AddIntAttribute(attribute, value.ToInt()); } void SetBoolAttribute(ax::mojom::blink::BoolAttribute attribute, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { // ARIA booleans are true if not "false" and not specifically undefined. @@ -31,7 +31,7 @@ } void SetStringAttribute(ax::mojom::blink::StringAttribute attribute, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { if (object->IsProhibited(attribute)) @@ -40,7 +40,7 @@ } void SetNotEmptyStringAttribute(ax::mojom::blink::StringAttribute attribute, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { if (value.length() != 0) @@ -49,7 +49,7 @@ void SetObjectAttribute(ax::mojom::blink::IntAttribute attribute, QualifiedName qualified_name, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { Element* element = object->GetElement(); @@ -74,7 +74,7 @@ void SetIntListAttribute(ax::mojom::blink::IntListAttribute attribute, QualifiedName qualified_name, - AXObject* object, + const AXObject* object, ui::AXNodeData* node_data, const AtomicString& value) { if (object->IsProhibited(attribute)) { @@ -94,7 +94,7 @@ AXObject* ax_element = object->AXObjectCache().Get(associated_element); if (!ax_element) continue; - if (!ax_element->AccessibilityIsIgnored()) + if (!ax_element->IsIgnored()) ax_ids.push_back(ax_element->AXObjectID()); } node_data->AddIntListAttribute(attribute, ax_ids); @@ -281,7 +281,7 @@ if (accessible_node) { Element* element = accessible_node->element(); AXObject* ax_element = ax_object_cache_->Get(element); - if (ax_element && !ax_element->AccessibilityIsIgnored()) + if (ax_element && !ax_element->IsIgnored()) ax_ids.push_back(ax_element->AXObjectID()); } }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h index 2993d684..2a0a602 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h +++ b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h
@@ -22,7 +22,7 @@ // accessibility attribute. using AXSparseSetterFunc = - base::RepeatingCallback<void(AXObject* ax_object, + base::RepeatingCallback<void(const AXObject* ax_object, ui::AXNodeData* node_data, const AtomicString& value)>; using AXSparseAttributeSetterMap = HashMap<QualifiedName, AXSparseSetterFunc>;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc b/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc index b4d8e5c..afdc8fc 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_validation_message.cc
@@ -18,7 +18,7 @@ AXValidationMessage::~AXValidationMessage() {} -bool AXValidationMessage::ComputeAccessibilityIsIgnored( +bool AXValidationMessage::ComputeIsIgnored( IgnoredReasons* ignored_reasons) const { return false; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_validation_message.h b/third_party/blink/renderer/modules/accessibility/ax_validation_message.h index ae80994..4c48c92 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_validation_message.h +++ b/third_party/blink/renderer/modules/accessibility/ax_validation_message.h
@@ -30,7 +30,7 @@ // Always a leaf. bool CanHaveChildren() const override { return false; } void AddChildren() override {} - bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override; + bool ComputeIsIgnored(IgnoredReasons* = nullptr) const override; void GetRelativeBounds(AXObject** out_container, gfx::RectF& out_bounds_in_container, gfx::Transform& out_container_transform,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc b/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc index 4786468e..69dfa5aa 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc
@@ -64,7 +64,7 @@ ax_child->UpdateCachedAttributeValuesIfNeeded( /*notify_parent_of_ignored_changes*/ false); DCHECK(!ax_child->IsDetached()); - DCHECK(ax_child->AccessibilityIsIncludedInTree()); + DCHECK(ax_child->IsIncludedInTree()); children_.push_back(ax_child); }
diff --git a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc index df96d4f..ccaad1d8 100644 --- a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc +++ b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc
@@ -28,31 +28,6 @@ namespace blink { -namespace { - -#if DCHECK_IS_ON() -AXObject* ParentObjectUnignored(AXObject* child) { - if (!child || child->IsDetached()) - return nullptr; - AXObject* parent = child->ParentObjectIncludedInTree(); - while (parent && !parent->IsDetached() && - !parent->AccessibilityIsIncludedInTree()) - parent = parent->ParentObjectIncludedInTree(); - return parent; -} - -// Check that |parent| is the first unignored parent of |child|. -void CheckParentUnignoredOf(AXObject* parent, AXObject* child) { - AXObject* preexisting_parent = ParentObjectUnignored(child); - DCHECK(preexisting_parent == parent) - << "Child thinks it has a different preexisting parent:" - << "\nChild: " << child << "\nPassed-in parent: " << parent - << "\nPreexisting parent: " << preexisting_parent; -} -#endif - -} // namespace - BlinkAXTreeSource::BlinkAXTreeSource(AXObjectCacheImpl& ax_object_cache, bool truncate_inline_textboxes) : ax_object_cache_(ax_object_cache), @@ -75,10 +50,10 @@ void BlinkAXTreeSource::Selection( const AXObject* obj, bool& is_selection_backward, - AXObject** anchor_object, + const AXObject** anchor_object, int& anchor_offset, ax::mojom::blink::TextAffinity& anchor_affinity, - AXObject** focus_object, + const AXObject** focus_object, int& focus_offset, ax::mojom::blink::TextAffinity& focus_affinity) const { is_selection_backward = false; @@ -92,7 +67,7 @@ if (!obj || obj->IsDetached()) return; - AXObject* focus = GetFocusedObject(); + const AXObject* focus = GetFocusedObject(); if (!focus || focus->IsDetached()) return; @@ -104,9 +79,9 @@ return; const AXPosition base = ax_selection.Anchor(); - *anchor_object = const_cast<AXObject*>(base.ContainerObject()); + *anchor_object = base.ContainerObject(); const AXPosition extent = ax_selection.Focus(); - *focus_object = const_cast<AXObject*>(extent.ContainerObject()); + *focus_object = extent.ContainerObject(); is_selection_backward = base > extent; if (base.IsTextPosition()) { @@ -134,7 +109,7 @@ bool BlinkAXTreeSource::GetTreeData(ui::AXTreeData* tree_data) const { CHECK(frozen_); - AXObject* root = GetRoot(); + const AXObject* root = GetRoot(); tree_data->doctype = "html"; tree_data->loaded = root->IsLoaded(); tree_data->loading_progress = root->EstimatedLoadingProgress(); @@ -143,11 +118,11 @@ tree_data->title = document.title().Utf8(); tree_data->url = document.Url().GetString().Utf8(); - if (AXObject* focus = GetFocusedObject()) + if (const AXObject* focus = GetFocusedObject()) tree_data->focus_id = focus->AXObjectID(); bool is_selection_backward = false; - AXObject *anchor_object, *focus_object; + const AXObject *anchor_object, *focus_object; int anchor_offset, focus_offset; ax::mojom::blink::TextAffinity anchor_affinity, focus_affinity; Selection(root, is_selection_backward, &anchor_object, anchor_offset, @@ -227,21 +202,21 @@ focus_ = nullptr; } -AXObject* BlinkAXTreeSource::GetRoot() const { +const AXObject* BlinkAXTreeSource::GetRoot() const { CHECK(frozen_); CHECK(root_); - return root_.Get(); + return root_; } -AXObject* BlinkAXTreeSource::GetFocusedObject() const { +const AXObject* BlinkAXTreeSource::GetFocusedObject() const { CHECK(frozen_); CHECK(focus_); - return focus_.Get(); + return focus_; } -AXObject* BlinkAXTreeSource::GetFromId(int32_t id) const { - AXObject* result = ax_object_cache_->ObjectFromAXID(id); - if (result && !result->AccessibilityIsIncludedInTree()) { +const AXObject* BlinkAXTreeSource::GetFromId(int32_t id) const { + const AXObject* result = ax_object_cache_->ObjectFromAXID(id); + if (result && !result->IsIncludedInTree()) { DCHECK(false) << "Should not serialize an unincluded object:" << "\nChild: " << result->ToString().Utf8(); return nullptr; @@ -249,11 +224,11 @@ return result; } -int32_t BlinkAXTreeSource::GetId(AXObject* node) const { +int32_t BlinkAXTreeSource::GetId(const AXObject* node) const { return node->AXObjectID(); } -size_t BlinkAXTreeSource::GetChildCount(AXObject* node) const { +size_t BlinkAXTreeSource::GetChildCount(const AXObject* node) const { if (truncate_inline_textboxes_ && ui::CanHaveInlineTextBoxChildren(node->RoleValue())) { return 0; @@ -261,7 +236,7 @@ return node->ChildCountIncludingIgnored(); } -AXObject* BlinkAXTreeSource::ChildAt(AXObject* node, size_t index) const { +AXObject* BlinkAXTreeSource::ChildAt(const AXObject* node, size_t index) const { if (truncate_inline_textboxes_) { CHECK(!ui::CanHaveInlineTextBoxChildren(node->RoleValue())); } @@ -276,7 +251,7 @@ return nullptr; } - if (!child->AccessibilityIsIncludedInTree()) { + if (!child->IsIncludedInTree()) { NOTREACHED(base::NotFatalUntil::M127) << "Should not receive unincluded child." << "\nChild: " << child->ToString().Utf8() @@ -288,35 +263,25 @@ // handled in AXTableInfo on the browser side. DCHECK_NE(child->RoleValue(), ax::mojom::blink::Role::kColumn); DCHECK_NE(child->RoleValue(), ax::mojom::blink::Role::kTableHeaderContainer); - -#if DCHECK_IS_ON() - CheckParentUnignoredOf(node, child); -#endif + DCHECK(child->ParentObjectIncludedInTree() == node) + << "Child thinks it has a different preexisting parent:" + << "\nChild: " << child << "\nPassed-in parent: " << node + << "\nPreexisting parent: " << child->ParentObjectIncludedInTree(); return child; } -AXObject* BlinkAXTreeSource::GetParent(AXObject* node) const { - // Blink returns ignored objects when walking up the parent chain, - // we have to skip those here. Also, stop when we get to the root - // element. - do { - if (node == GetRoot()) - return nullptr; - node = node->ParentObject(); - } while (node && !node->IsDetached() && - !node->AccessibilityIsIncludedInTree()); - - return node; +AXObject* BlinkAXTreeSource::GetParent(const AXObject* node) const { + return node->ParentObjectIncludedInTree(); } -bool BlinkAXTreeSource::IsIgnored(AXObject* node) const { +bool BlinkAXTreeSource::IsIgnored(const AXObject* node) const { if (!node || node->IsDetached()) return false; - return node->AccessibilityIsIgnored(); + return node->IsIgnored(); } -bool BlinkAXTreeSource::IsEqual(AXObject* node1, AXObject* node2) const { +bool BlinkAXTreeSource::IsEqual(const AXObject* node1, const AXObject* node2) const { return node1 == node2; } @@ -324,13 +289,13 @@ return nullptr; } -std::string BlinkAXTreeSource::GetDebugString(AXObject* node) const { +std::string BlinkAXTreeSource::GetDebugString(const AXObject* node) const { if (!node || node->IsDetached()) return ""; return node->ToString().Utf8(); } -void BlinkAXTreeSource::SerializeNode(AXObject* src, +void BlinkAXTreeSource::SerializeNode(const AXObject* src, ui::AXNodeData* dst) const { #if DCHECK_IS_ON() // Never causes a document lifecycle change during serialization, @@ -339,7 +304,7 @@ ax_object_cache_->GetDocument().Lifecycle()); #endif - if (!src || src->IsDetached() || !src->AccessibilityIsIncludedInTree()) { + if (!src || src->IsDetached() || !src->IsIncludedInTree()) { dst->AddState(ax::mojom::blink::State::kIgnored); dst->id = -1; dst->role = ax::mojom::blink::Role::kUnknown;
diff --git a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.h b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.h index 8ad7488b..4fca0b3 100644 --- a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.h +++ b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.h
@@ -29,7 +29,7 @@ class MODULES_EXPORT BlinkAXTreeSource : public GarbageCollected<BlinkAXTreeSource>, - public ui::AXTreeSource<AXObject*, ui::AXTreeData*, ui::AXNodeData> { + public ui::AXTreeSource<const AXObject*, ui::AXTreeData*, ui::AXNodeData> { public: // Pass truncate_inline_textboxes_ if inline textboxes should be removed // from the serialized tree, even if they are already available in the cache. @@ -45,19 +45,19 @@ // AXTreeSource implementation. bool GetTreeData(ui::AXTreeData* tree_data) const override; - AXObject* GetRoot() const override; - AXObject* GetFromId(int32_t id) const override; - int32_t GetId(AXObject* node) const override; - void CacheChildrenIfNeeded(AXObject*) override {} - size_t GetChildCount(AXObject* node) const override; - AXObject* ChildAt(AXObject* node, size_t) const override; - void ClearChildCache(AXObject*) override {} - AXObject* GetParent(AXObject* node) const override; - void SerializeNode(AXObject* node, ui::AXNodeData* out_data) const override; - bool IsIgnored(AXObject* node) const override; - bool IsEqual(AXObject* node1, AXObject* node2) const override; + const AXObject* GetRoot() const override; + const AXObject* GetFromId(int32_t id) const override; + int32_t GetId(const AXObject* node) const override; + void CacheChildrenIfNeeded(const AXObject*) override {} + size_t GetChildCount(const AXObject* node) const override; + AXObject* ChildAt(const AXObject* node, size_t) const override; + void ClearChildCache(const AXObject*) override {} + AXObject* GetParent(const AXObject* node) const override; + void SerializeNode(const AXObject* node, ui::AXNodeData* out_data) const override; + bool IsIgnored(const AXObject* node) const override; + bool IsEqual(const AXObject* node1, const AXObject* node2) const override; AXObject* GetNull() const override; - std::string GetDebugString(AXObject* node) const override; + std::string GetDebugString(const AXObject* node) const override; // Ignore code that limits based on the protocol (like https, file, etc.) // to enable tests to run. @@ -72,14 +72,14 @@ private: void Selection(const AXObject* obj, bool& is_selection_backward, - AXObject** anchor_object, + const AXObject** anchor_object, int& anchor_offset, ax::mojom::blink::TextAffinity& anchor_affinity, - AXObject** focus_object, + const AXObject** focus_object, int& focus_offset, ax::mojom::blink::TextAffinity& focus_affinity) const; - AXObject* GetFocusedObject() const; + const AXObject* GetFocusedObject() const; // Whether we should highlight annotation results visually on the page // for debugging. @@ -89,8 +89,8 @@ bool frozen_ = false; // TODO(accessibility) If caching these does not improv perf, remove these. - Member<AXObject> root_ = nullptr; - Member<AXObject> focus_ = nullptr; + Member<const AXObject> root_ = nullptr; + Member<const AXObject> focus_ = nullptr; // The AxID of the first unlabeled image we have encountered in this tree. //
diff --git a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc index a76951d..a5c3f52 100644 --- a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc +++ b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -563,7 +563,7 @@ return protocol::Response::Success(); } - if (inspected_ax_object && !inspected_ax_object->AccessibilityIsIgnored()) + if (inspected_ax_object && !inspected_ax_object->IsIgnored()) AddChildren(*inspected_ax_object, true, *nodes, cache); AXObject* parent_ax_object; @@ -598,7 +598,7 @@ BuildProtocolAXNodeForAXObject(first_ancestor); // Since the inspected node is ignored it is missing from the first ancestors // childIds. We therefore add it to maintain the tree structure: - if (!inspected_ax_object || inspected_ax_object->AccessibilityIsIgnored()) { + if (!inspected_ax_object || inspected_ax_object->IsIgnored()) { auto child_ids = std::make_unique<protocol::Array<AXNodeId>>(); auto* existing_child_ids = first_parent_node_object->getChildIds(nullptr); @@ -649,7 +649,7 @@ AXObject& ax_object, bool force_name_and_role) const { std::unique_ptr<protocol::Accessibility::AXNode> protocol_node; - if (ax_object.AccessibilityIsIgnored()) { + if (ax_object.IsIgnored()) { protocol_node = BuildProtocolAXNodeForIgnoredAXObject(ax_object, force_name_and_role); } else { @@ -705,7 +705,7 @@ // Compute and attach reason for node to be ignored: AXObject::IgnoredReasons ignored_reasons; - ax_object.ComputeAccessibilityIsIgnored(&ignored_reasons); + ax_object.ComputeIsIgnored(&ignored_reasons); auto ignored_reason_properties = std::make_unique<protocol::Array<AXProperty>>(); for (IgnoredReason& reason : ignored_reasons) @@ -996,7 +996,7 @@ // If the node is ignored or has no corresponding DOM node, we include // another layer of children. if (follow_ignored && - (descendant->AccessibilityIsIgnoredButIncludedInTree() || + (descendant->IsIgnoredButIncludedInTree() || !descendant->GetNode())) { reachable.AppendRange(descendant->ChildrenIncludingIgnored().rbegin(), descendant->ChildrenIncludingIgnored().rend()); @@ -1093,7 +1093,7 @@ while (!reachable.empty()) { AXObject* ax_object = reachable.back(); if (ax_object->IsDetached() || - !ax_object->AccessibilityIsIncludedInTree()) { + !ax_object->IsIncludedInTree()) { reachable.pop_back(); continue; } @@ -1104,7 +1104,7 @@ ax_object->ChildrenIncludingIgnored(); reachable.AppendRange(children.rbegin(), children.rend()); - const bool ignored = ax_object->AccessibilityIsIgnored(); + const bool ignored = ax_object->IsIgnored(); // if querying by name: skip if name of current object does not match. // For now, we need to handle names of ignored nodes separately, since they // do not get a name assigned when serializing to AXNodeData. @@ -1221,7 +1221,7 @@ ax::mojom::blink::Event event) { if (!enabled_.Get()) return; - DCHECK(ax_object->AccessibilityIsIncludedInTree()); + DCHECK(ax_object->IsIncludedInTree()); switch (event) { case ax::mojom::blink::Event::kLoadComplete: { @@ -1254,14 +1254,14 @@ bool subtree) { if (!enabled_.Get()) return; - DCHECK(ax_object->AccessibilityIsIncludedInTree()); + DCHECK(ax_object->IsIncludedInTree()); if (subtree) { HeapVector<Member<AXObject>> reachable; reachable.push_back(ax_object); while (!reachable.empty()) { AXObject* descendant = reachable.back(); reachable.pop_back(); - DCHECK(descendant->AccessibilityIsIncludedInTree()); + DCHECK(descendant->IsIncludedInTree()); if (!MarkAXObjectDirty(descendant)) continue; const AXObject::AXObjectVector& children =
diff --git a/third_party/blink/renderer/modules/accessibility/testing/internals_accessibility.cc b/third_party/blink/renderer/modules/accessibility/testing/internals_accessibility.cc index 2c01cba..92ef411 100644 --- a/third_party/blink/renderer/modules/accessibility/testing/internals_accessibility.cc +++ b/third_party/blink/renderer/modules/accessibility/testing/internals_accessibility.cc
@@ -29,7 +29,7 @@ WTF::String InternalsAccessibility::getComputedLabel(Internals&, const Element* element) { AXObject* ax_object = GetAXObject(element); - if (!ax_object || ax_object->AccessibilityIsIgnored()) { + if (!ax_object || ax_object->IsIgnored()) { return g_empty_string; } @@ -42,7 +42,7 @@ WTF::String InternalsAccessibility::getComputedRole(Internals&, const Element* element) { AXObject* ax_object = GetAXObject(element); - if (!ax_object || ax_object->AccessibilityIsIgnored()) { + if (!ax_object || ax_object->IsIgnored()) { return AXObject::AriaRoleName(ax::mojom::Role::kNone); }
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc index 94fd338..6fa7d434 100644 --- a/third_party/blink/renderer/modules/exported/web_ax_object.cc +++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -738,14 +738,14 @@ return WebDocument(document); } -bool WebAXObject::AccessibilityIsIgnored() const { +bool WebAXObject::IsIgnored() const { if (IsDetached()) return false; - return private_->AccessibilityIsIgnored(); + return private_->IsIgnored(); } -bool WebAXObject::AccessibilityIsIncludedInTree() const { +bool WebAXObject::IsIncludedInTree() const { if (IsDetached()) return false; @@ -755,7 +755,7 @@ << "Document lifecycle must be at LayoutClean or later, was " << private_->GetDocument()->Lifecycle().GetState(); - return private_->AccessibilityIsIncludedInTree(); + return private_->IsIncludedInTree(); } unsigned WebAXObject::ColumnCount() const {
diff --git a/third_party/blink/renderer/modules/mediasource/html_video_element_media_source.idl b/third_party/blink/renderer/modules/mediasource/html_video_element_media_source.idl index 765cf26..2f3cfdb 100644 --- a/third_party/blink/renderer/modules/mediasource/html_video_element_media_source.idl +++ b/third_party/blink/renderer/modules/mediasource/html_video_element_media_source.idl
@@ -29,8 +29,7 @@ */ [ - ImplementedAs=HTMLVideoElementMediaSource, - RuntimeEnabled=VideoPlaybackQuality + ImplementedAs=HTMLVideoElementMediaSource ] partial interface HTMLVideoElement { [Measure] VideoPlaybackQuality getVideoPlaybackQuality(); };
diff --git a/third_party/blink/renderer/modules/mediasource/video_playback_quality.idl b/third_party/blink/renderer/modules/mediasource/video_playback_quality.idl index f93c17a..7405cc9 100644 --- a/third_party/blink/renderer/modules/mediasource/video_playback_quality.idl +++ b/third_party/blink/renderer/modules/mediasource/video_playback_quality.idl
@@ -28,8 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ [ - Exposed=Window, - RuntimeEnabled=VideoPlaybackQuality + Exposed=Window ] interface VideoPlaybackQuality { readonly attribute DOMHighResTimeStamp creationTime; readonly attribute unsigned long totalVideoFrames;
diff --git a/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc b/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc index c70c8c2..ff99f8dc 100644 --- a/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc +++ b/third_party/blink/renderer/modules/ml/ml_trace_unittest.cc
@@ -53,7 +53,7 @@ base::trace_event::TraceResultBuffer trace_buffer; trace_buffer.SetOutputCallback(json_output->GetCallback()); trace_buffer.Start(); - trace_buffer.AddFragment(json_events_str->data()); + trace_buffer.AddFragment(json_events_str->as_string()); trace_buffer.Finish(); if (!has_more_events) { std::move(quit_closure).Run();
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc index fa3d9a3..a943374 100644 --- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc +++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -190,7 +190,8 @@ return; } auto* task_info = MakeGarbageCollected<TaskAttributionInfoImpl>( - scheduler::TaskAttributionId(task_id)); + scheduler::TaskAttributionId(task_id), + /*soft_navigation_context=*/nullptr); ScriptWrappableTaskState::SetCurrent(script_state, task_info); }
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.cc b/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.cc index 6321f1be..e8b7060 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.cc +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.cc
@@ -5,15 +5,18 @@ #include "third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.h" #include "third_party/blink/public/common/scheduler/task_attribution_id.h" +#include "third_party/blink/renderer/core/timing/soft_navigation_context.h" namespace blink { TaskAttributionInfoImpl::TaskAttributionInfoImpl( - scheduler::TaskAttributionId id) - : id_(id) {} + scheduler::TaskAttributionId id, + SoftNavigationContext* soft_navigation_context) + : id_(id), soft_navigation_context_(soft_navigation_context) {} void TaskAttributionInfoImpl::Trace(Visitor* visitor) const { ScriptWrappableTaskState::Trace(visitor); + visitor->Trace(soft_navigation_context_); } AbortSignal* TaskAttributionInfoImpl::AbortSource() { @@ -29,6 +32,10 @@ return this; } +SoftNavigationContext* TaskAttributionInfoImpl::GetSoftNavigationContext() { + return soft_navigation_context_.Get(); +} + scheduler::TaskAttributionId TaskAttributionInfoImpl::Id() const { return id_; }
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.h b/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.h index 3bbbe9a8..3abb5233 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.h +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_info_impl.h
@@ -15,12 +15,13 @@ namespace blink { class AbortSignal; class DOMTaskSignal; +class SoftNavigationContext; class MODULES_EXPORT TaskAttributionInfoImpl final : public ScriptWrappableTaskState, public scheduler::TaskAttributionInfo { public: - explicit TaskAttributionInfoImpl(scheduler::TaskAttributionId id); + TaskAttributionInfoImpl(scheduler::TaskAttributionId, SoftNavigationContext*); // `ScriptWrappableTaskState` implementation: AbortSignal* AbortSource() override; @@ -29,11 +30,13 @@ // `scheduler::TaskAttributionInfo` implementation: scheduler::TaskAttributionId Id() const override; + SoftNavigationContext* GetSoftNavigationContext() override; void Trace(Visitor*) const override; private: const scheduler::TaskAttributionId id_; + Member<SoftNavigationContext> soft_navigation_context_; }; // `TaskAttributionInfoImpl` is the only implementation of
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc index d1aca162..0fadff6bb 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.cc
@@ -46,6 +46,8 @@ return ProtoType::TASK_SCOPE_REQUEST_IDLE_CALLBACK; case TaskAttributionTracker::TaskScopeType::kXMLHttpRequest: return ProtoType::TASK_SCOPE_XML_HTTP_REQUEST; + case TaskAttributionTracker::TaskScopeType::kSoftNavigation: + return ProtoType::TASK_SCOPE_SOFT_NAVIGATION; } } @@ -83,6 +85,17 @@ TaskAttributionTracker::TaskScope TaskAttributionTrackerImpl::CreateTaskScope( ScriptState* script_state, + SoftNavigationContext* soft_navigation_context) { + next_task_id_ = next_task_id_.NextId(); + auto* task_state = MakeGarbageCollected<TaskAttributionInfoImpl>( + next_task_id_, soft_navigation_context); + return CreateTaskScope(script_state, task_state, + TaskScopeType::kSoftNavigation, + /*abort_source=*/nullptr, /*priority_source=*/nullptr); +} + +TaskAttributionTracker::TaskScope TaskAttributionTrackerImpl::CreateTaskScope( + ScriptState* script_state, TaskAttributionInfo* task_state, TaskScopeType type, AbortSignal* abort_source, @@ -96,7 +109,8 @@ // state to begin propagating. if (!task_state) { next_task_id_ = next_task_id_.NextId(); - task_state = MakeGarbageCollected<TaskAttributionInfoImpl>(next_task_id_); + task_state = MakeGarbageCollected<TaskAttributionInfoImpl>( + next_task_id_, /*soft_navigation_contxt=*/nullptr); } ScriptWrappableTaskState* running_task_state = nullptr; @@ -118,7 +132,12 @@ // Fire observer callbacks after updating the CPED to keep `RunningTask()` in // sync with what is passed to the observer. - if (observer_) { + // + // TODO(crbug.com/40942324): The purpose of the `Observer` mechanism is so the + // soft navigation layer can learn if an event ran while the scope is active, + // which is why we filter out soft navigation task scopes. It might be better + // to move event observation into event handling itself. + if (observer_ && type != TaskScopeType::kSoftNavigation) { observer_->OnCreateTaskScope(*current); } @@ -135,6 +154,31 @@ return TaskScope(this, script_state, previous_task_state); } +std::optional<TaskAttributionTracker::TaskScope> +TaskAttributionTrackerImpl::MaybeCreateTaskScopeForCallback( + ScriptState* script_state, + TaskAttributionInfo* task_state) { + CHECK(script_state); + + TaskAttributionInfo* current_task_state = RunningTask(); + // Always create a `TaskScope` if there's `task_state` to propagate. Always + // create a `TaskScope` if there's no `current_task_state` to ensure there's a + // `TaskScope` for top-level JS execution. + if (task_state || !current_task_state) { + return CreateTaskScope(script_state, task_state, TaskScopeType::kCallback); + } + + // Even though we don't need to create a `TaskScope`, we still need to notify + // the `observer_` since it relies on the callback to set up internal state. + // And the `observer_` might not have been notified previously, e.g. if + // the outermost `TaskScope` is for propagating soft navigation state. + if (observer_) { + observer_->OnCreateTaskScope(*current_task_state); + } + + return std::nullopt; +} + void TaskAttributionTrackerImpl::OnTaskScopeDestroyed( const TaskScope& task_scope) { ScriptWrappableTaskState::SetCurrent(task_scope.script_state_, @@ -183,10 +227,4 @@ return nullptr; } -TaskAttributionInfo* -TaskAttributionTrackerImpl::CreateTaskAttributionInfoForTest( - TaskAttributionId id) { - return MakeGarbageCollected<TaskAttributionInfoImpl>(id); -} - } // namespace blink::scheduler
diff --git a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h index 70c44a29..9c32e01 100644 --- a/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h +++ b/third_party/blink/renderer/modules/scheduler/task_attribution_tracker_impl.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_ATTRIBUTION_TRACKER_IMPL_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_ATTRIBUTION_TRACKER_IMPL_H_ +#include <optional> + #include "base/containers/contains.h" #include "base/memory/raw_ptr.h" #include "third_party/blink/public/common/scheduler/task_attribution_id.h" @@ -18,6 +20,7 @@ namespace blink { class AbortSignal; class DOMTaskSignal; +class SoftNavigationContext; } // namespace blink namespace v8 { @@ -45,19 +48,23 @@ TaskScopeType type) override; TaskScope CreateTaskScope(ScriptState* script_state, + SoftNavigationContext*) override; + + TaskScope CreateTaskScope(ScriptState* script_state, TaskAttributionInfo* task_state, TaskScopeType type, AbortSignal* abort_source, DOMTaskSignal* priority_source) override; + std::optional<TaskScope> MaybeCreateTaskScopeForCallback( + ScriptState*, + TaskAttributionInfo* task_state) override; + ObserverScope RegisterObserver(Observer* observer) override; void AddSameDocumentNavigationTask(TaskAttributionInfo* task) override; void ResetSameDocumentNavigationTasks() override; TaskAttributionInfo* CommitSameDocumentNavigation(TaskAttributionId) override; - TaskAttributionInfo* CreateTaskAttributionInfoForTest( - TaskAttributionId id) override; - private: explicit TaskAttributionTrackerImpl(v8::Isolate*);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc index 992c1009..bf0c9d3 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -2112,6 +2112,17 @@ return width_; } +float ShapeResult::CachedWidth(unsigned start_offset, + unsigned end_offset) const { + const unsigned offset_adjust = StartIndex(); + const float start_position = + CachedPositionForOffset(start_offset - offset_adjust); + const float end_position = + CachedPositionForOffset(end_offset - offset_adjust); + return IsLtr() ? end_position - start_position + : start_position - end_position; +} + unsigned ShapeResult::CachedNextSafeToBreakOffset(unsigned offset) const { if (IsRtl()) { return NextSafeToBreakOffset(offset);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h index a035f3eb..5e09f424 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -276,6 +276,7 @@ // does not take partial glyphs into account. unsigned CachedOffsetForPosition(float x) const; float CachedPositionForOffset(unsigned offset) const; + float CachedWidth(unsigned start_offset, unsigned end_offset) const; // Returns the next or previous offsets respectively at which it is safe to // break without reshaping. Operates on a cache (that needs to be pre-computed
diff --git a/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc index 66aab1a..d4c2310 100644 --- a/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/test/incremental_marking_test.cc
@@ -1332,9 +1332,6 @@ // Disable concurrent sweeping to check that sweeping is not in progress after // the FinishGC call. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - blink::features::kBlinkHeapConcurrentSweeping); using Container = HeapVector<Member<LinkedObject>>; Persistent<Container> holder(MakeGarbageCollected<Container>()); WeakPersistent<Container> canary(holder.Get());
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ed6c3cf7..4e99897 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3021,10 +3021,11 @@ status: "experimental", }, // This feature is deprecated and we are evangelizing affected sites. - // See https://crbug.com/346236 for current status. + // A deprecation trial is underway, starting in M125. + // See https://crbug.com/40352864 for current status { name: "PrefixedVideoFullscreen", - status: "stable", + status: "test", origin_trial_feature_name: "DeprecatePrefixedVideoFullscreen", origin_trial_type: "deprecation", origin_trial_allows_insecure: true, @@ -4035,12 +4036,6 @@ name: "VideoFullscreenOrientationLock", }, { - name: "VideoPlaybackQuality", - public: true, - status: "stable", - base_feature: "none", - }, - { name: "VideoRotateToFullscreen", }, {
diff --git a/third_party/blink/renderer/platform/scheduler/public/task_attribution_info.h b/third_party/blink/renderer/platform/scheduler/public/task_attribution_info.h index a084e84..3562e98 100644 --- a/third_party/blink/renderer/platform/scheduler/public/task_attribution_info.h +++ b/third_party/blink/renderer/platform/scheduler/public/task_attribution_info.h
@@ -9,6 +9,10 @@ #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/platform_export.h" +namespace blink { +class SoftNavigationContext; +} // namespace blink + namespace blink::scheduler { // Interface for task state that can be propagated to descendant tasks and @@ -16,7 +20,13 @@ class PLATFORM_EXPORT TaskAttributionInfo : public GarbageCollectedMixin { public: // Returns an id for this object, which is unique for the associated tracker. + // This is primarily used for tracking task state across IPCs, e.g. for + // navigation and postMessage. virtual TaskAttributionId Id() const = 0; + + // Returns the `SoftNavigationContext` associated with the task state, which + // can be null. + virtual SoftNavigationContext* GetSoftNavigationContext() = 0; }; } // namespace blink::scheduler
diff --git a/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h b/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h index e947c9b..efb19275 100644 --- a/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h +++ b/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_TASK_ATTRIBUTION_TRACKER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_TASK_ATTRIBUTION_TRACKER_H_ +#include <optional> #include <utility> #include "base/functional/function_ref.h" @@ -20,6 +21,7 @@ class DOMTaskSignal; class ScriptState; class ScriptWrappableTaskState; +class SoftNavigationContext; } // namespace blink namespace v8 { @@ -45,6 +47,7 @@ kSchedulerPostTask, kRequestIdleCallback, kXMLHttpRequest, + kSoftNavigation, }; // `TaskScope` stores state for the current task, which is propagated to tasks @@ -147,6 +150,10 @@ TaskAttributionInfo* task_state, TaskScopeType type) = 0; + // Create a new `TaskScope` to propagate the given `SoftNavigationContext`, + // initiating propagation for the context. + virtual TaskScope CreateTaskScope(ScriptState*, SoftNavigationContext*) = 0; + // Creates a new `TaskScope` with web scheduling context. `task_state` will be // propagated to descendant tasks and continuations; `abort_source` and // `priority_source` will only be propagated to continuations. @@ -156,6 +163,13 @@ AbortSignal* abort_source, DOMTaskSignal* priority_source) = 0; + // Conditionally create a `TaskScope` for a generic v8 callback. A `TaskScope` + // is always created if `task_state` is non-null, and one is additionally + // created if there isn't an active `TaskScope`. + virtual std::optional<TaskScope> MaybeCreateTaskScopeForCallback( + ScriptState*, + TaskAttributionInfo* task_state) = 0; + // Get the `TaskAttributionInfo` for the currently running task. virtual TaskAttributionInfo* RunningTask() const = 0; @@ -171,9 +185,6 @@ virtual TaskAttributionInfo* CommitSameDocumentNavigation( TaskAttributionId) = 0; - virtual TaskAttributionInfo* CreateTaskAttributionInfoForTest( - TaskAttributionId id) = 0; - protected: virtual void OnTaskScopeDestroyed(const TaskScope&) = 0; virtual void OnObserverScopeDestroyed(const ObserverScope&) = 0;
diff --git a/third_party/blink/renderer/platform/text/character_property_data_generator.cc b/third_party/blink/renderer/platform/text/character_property_data_generator.cc index 33fdc247..2b2503b4 100644 --- a/third_party/blink/renderer/platform/text/character_property_data_generator.cc +++ b/third_party/blink/renderer/platform/text/character_property_data_generator.cc
@@ -20,6 +20,7 @@ #include <fstream> #include <iterator> #include <memory> +#include <vector> #include "base/check_op.h" #include "base/containers/heap_array.h"
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 52f943c..6fdf9ab 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2652,9 +2652,6 @@ crbug.com/626703 external/wpt/uievents/mouse/mouse_boundary_events_after_removing_last_over_element.html [ Failure ] # ====== New tests from wpt-importer added here ====== -crbug.com/335324883 [ Mac12 ] external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html [ Timeout ] -crbug.com/335324883 [ Mac14 ] external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html [ Timeout ] -crbug.com/335324883 [ Mac13 ] external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html [ Timeout ] crbug.com/335330795 [ Mac14 ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/reduction.https.any.worker.html [ Skip Timeout ] crbug.com/335246098 external/wpt/css/css-viewport/zoom/iframe-zoom-nested.html [ Failure ] crbug.com/335246098 external/wpt/css/css-viewport/zoom/iframe-zoom.sub.html [ Failure ] @@ -7262,7 +7259,6 @@ crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-multicol/multicol-fill-balance-021.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/br-clear-all-002.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-break-around-ruby-001.html [ Failure ] -crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/line-spacing.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-ruby/ruby-line-breaking-002.html [ Failure ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-text-decor/ruby-text-decoration-01.html [ Crash ] crbug.com/324111880 virtual/ruby-lb/external/wpt/css/css-writing-modes/direction-upright-002.html [ Crash 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 2eac162..0bfc715 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
@@ -362579,6 +362579,10 @@ [] ], "render-blocking": { + "WEB_FEATURES.yml": [ + "36ab4f3010306b90fc1f47133087e94a3a0d445f", + [] + ], "support": { "dummy-1.js": [ "597772cf641d83b41f0e4238a1fa74a050f29d3c", @@ -366165,6 +366169,10 @@ "35449ec5bab7c3e8ac3c61fa50a8207e667eabe2", [] ], + "WEB_FEATURES.yml": [ + "210e2d3f99aea03af1675a0ec7bd222a05ca0236", + [] + ], "document-level-focus-apis": { "support": { "popup.html": [ @@ -366200,6 +366208,10 @@ } }, "sequential-focus-navigation-and-the-tabindex-attribute": { + "WEB_FEATURES.yml": [ + "6d868044c9e8c31421a0ebc33b868974f5cf079c", + [] + ], "resources": { "frameset-using-page.html": [ "e3aedea246e6f38904a4835c99c530a4777f41a6", @@ -366406,6 +366418,10 @@ "a7142360eb190ab0466fca43bfeb7a068c043b1d", [] ], + "WEB_FEATURES.yml": [ + "831b257f72b1619f1f48dab7ed0324ddfa71717a", + [] + ], "div-align-ref.html": [ "da8e4d0dc1a866cb0539c8a8f2028fbd3ee1ebc5", [] @@ -367207,6 +367223,10 @@ "72387ccff958b7a6fea9972a4f0cedad09e83c03", [] ], + "WEB_FEATURES.yml": [ + "769e741180af1e93f5ad453afc40c22adbaa281c", + [] + ], "details-display-property-is-ignored-ref.html": [ "6ebed6075de1e8cf62db7bee756b05d3e425e0ab", [] @@ -368964,6 +368984,10 @@ ] }, "the-object-element": { + "WEB_FEATURES.yml": [ + "d3411c2d8d2f45afdadc68967272102d2fdbbd4b", + [] + ], "object-attributes-expected.txt": [ "f7694843c68c36b6cd0a837ecfd367d9fcd8de23", [] @@ -369038,6 +369062,10 @@ } }, "constraints": { + "WEB_FEATURES.yml": [ + "93b4c5745fc7461b7e815a1d790243fb2ed4cb71", + [] + ], "support": { "validator.js": [ "aa43b3a2f6afd63b745bdb78fefc1b086628e5ef", @@ -369152,6 +369180,10 @@ "4881f7e9eece3beb376c2b42cd4ad7e9c6a4413c", [] ], + "WEB_FEATURES.yml": [ + "f5a2aeaf4f829af3560e13cede06368e9b03e931", + [] + ], "button-activate-frame.html": [ "37619d79123be6855744ab82d65f2e72fe56bf04", [] @@ -369176,6 +369208,10 @@ "66c747a5b5224140e9bcae06106116307db2157c", [] ], + "WEB_FEATURES.yml": [ + "912cb47c6d02d3ca01b930da37cd549afb69a5ee", + [] + ], "accessibility": { "README.md": [ "b238a023dc1344b9b35f0850bf75950e49edfdc7", @@ -369184,6 +369220,10 @@ } }, "the-form-element": { + "WEB_FEATURES.yml": [ + "04c20cb5ece542108f6c82693f6e144c55573f6b", + [] + ], "form-nameditem-expected.txt": [ "47a173633148e0f8237d9b7fc7560989ffda68f4", [] @@ -369214,6 +369254,10 @@ } }, "the-input-element": { + "WEB_FEATURES.yml": [ + "4957615f2477552fb6075f1cc6e64915ecd743ce", + [] + ], "auto-direction-ref.html": [ "675ba509144515a44e06f39dd1ac727b4a2d2bc6", [] @@ -369363,6 +369407,10 @@ "DIR_METADATA": [ "5f96515e41ec80c00c0fd4075b1a4f15c274879d", [] + ], + "WEB_FEATURES.yml": [ + "2f7f8e8cc2d81246a26de7ab69184036883f6999", + [] ] }, "the-progress-element": { @@ -369376,6 +369424,10 @@ "c8ba5e73831c7af891acb9ba7fd72d83926a78c9", [] ], + "WEB_FEATURES.yml": [ + "9695c9529424d612300127b3350254e15a05c27e", + [] + ], "reset-algorithm-rendering-ref.html": [ "acf192d1d55b7da110d04651093e3ebe0cd48214", [] @@ -369524,6 +369576,10 @@ "67b102f814349e5a672d01449796307ee7a37316", [] ], + "WEB_FEATURES.yml": [ + "14479d4bb3d44a72130eb7008e93b7b379bab48f", + [] + ], "multiline-placeholder-ref.html": [ "0234ed64c9ad7155a42b254a5fe35a39535cbff8", [] @@ -369678,6 +369734,10 @@ "72387ccff958b7a6fea9972a4f0cedad09e83c03", [] ], + "WEB_FEATURES.yml": [ + "be3924a26adb1663caf3f964fe51d97e3fd695f2", + [] + ], "details-add-summary-ref.html": [ "14f2be232fb4aba0afb4542213331995fcb12575", [] @@ -371778,6 +371838,10 @@ } }, "the-template-element": { + "WEB_FEATURES.yml": [ + "bd821885c7b7d4add4db186a9a94a14181cc3d38", + [] + ], "additions-to-the-css-user-agent-style-sheet": { "css-user-agent-style-sheet-test-001-ref.html": [ "55c8b2e30c9d5353d03a09c195098f70d7b76fd2", @@ -371912,6 +371976,10 @@ ] }, "pseudo-classes": { + "WEB_FEATURES.yml": [ + "604e049f202c94d9bd55edefd7b09f57cd9fedf6", + [] + ], "checked-indeterminate.window-expected.txt": [ "15e63a9a7ad831ff201eb05ee60f1c6b2ce189ee", [] @@ -372333,6 +372401,12 @@ [] ] }, + "template": { + "WEB_FEATURES.yml": [ + "bd821885c7b7d4add4db186a9a94a14181cc3d38", + [] + ] + }, "template.js": [ "b249fb64c71c16f1b6cefcc59668699f769a2341", [] @@ -373999,6 +374073,10 @@ } }, "structured-clone": { + "WEB_FEATURES.yml": [ + "423a469bf17283e0ec8d32d0e7debdc8eeb1fce2", + [] + ], "structured-clone-battery-of-tests-harness.js": [ "00a86fa74b9a968dabae400f57dd32ffb836aa2c", [] @@ -384522,7 +384600,7 @@ [] ], "testharnessreport.js": [ - "e5cb40fe0ef652be407d4c48b1c59391864cec7b", + "405a2d8b06f00fe8292e0e9d5b917e193cfd416c", [] ], "testharnessreport.js.headers": [ @@ -461293,6 +461371,15 @@ ] ] }, + "snap-events-with-pseudo-target.tentative.html": [ + "baa3efc7ba7cd5c4a182b44a7e7d88a107f826fa", + [ + null, + { + "testdriver": true + } + ] + ], "snapchanged": { "snapchanged-after-layout-change.tentative.html": [ "a3ba05fdf5e9ffa42ab5689349e33b3c9a0aee15",
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/WEB_FEATURES.yml new file mode 100644 index 0000000..36ab4f3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: blocking-render + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/interaction/focus/WEB_FEATURES.yml new file mode 100644 index 0000000..210e2d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/WEB_FEATURES.yml
@@ -0,0 +1,4 @@ +features: +- name: tabindex + files: + - tabindex-focus-flag.html
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/WEB_FEATURES.yml new file mode 100644 index 0000000..6d868044 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: tabindex + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/WEB_FEATURES.yml new file mode 100644 index 0000000..831b257 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/flow-content-0/WEB_FEATURES.yml
@@ -0,0 +1,4 @@ +features: +- name: search + files: + - search-*
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/WEB_FEATURES.yml new file mode 100644 index 0000000..769e741 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: details + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/WEB_FEATURES.yml new file mode 100644 index 0000000..d3411c2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-object-element/WEB_FEATURES.yml
@@ -0,0 +1,4 @@ +features: +- name: constraint-validation + files: + - object-setcustomvalidity.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/WEB_FEATURES.yml new file mode 100644 index 0000000..93b4c57 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: constraint-validation + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/WEB_FEATURES.yml new file mode 100644 index 0000000..f5a2aea --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-button-element/WEB_FEATURES.yml
@@ -0,0 +1,10 @@ +features: +- name: constraint-validation + files: + - button-checkvalidity.html + - button-setcustomvalidity.html + - button-validation.html + - button-validationmessage.html + - button-validity.html + - button-willvalidate-readonly-attribute.html + - button-willvalidate.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-fieldset-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-fieldset-element/WEB_FEATURES.yml new file mode 100644 index 0000000..912cb47c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-fieldset-element/WEB_FEATURES.yml
@@ -0,0 +1,8 @@ +features: +- name: constraint-validation + files: + - fieldset-checkvalidity.html + - fieldset-setcustomvalidity.html + - fieldset-validationmessage.html + - fieldset-validity.html + - fieldset-willvalidate.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-form-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-form-element/WEB_FEATURES.yml new file mode 100644 index 0000000..04c20cb5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-form-element/WEB_FEATURES.yml
@@ -0,0 +1,4 @@ +features: +- name: constraint-validation + files: + - form-checkvalidity.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/WEB_FEATURES.yml new file mode 100644 index 0000000..4957615f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-input-element/WEB_FEATURES.yml
@@ -0,0 +1,11 @@ +features: +- name: constraint-validation + files: + - input-checkvalidity.html + - input-setcustomvalidity.html + - input-validationmessage.html + - input-validity.html + - input-willvalidate.html +- name: show-picker-input + files: + - show-picker-*
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/WEB_FEATURES.yml new file mode 100644 index 0000000..2f7f8e8c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-output-element/WEB_FEATURES.yml
@@ -0,0 +1,5 @@ +features: +- name: constraint-validation + files: + - output-setcustomvalidity.html + - output-validity.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/WEB_FEATURES.yml new file mode 100644 index 0000000..9695c952 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/WEB_FEATURES.yml
@@ -0,0 +1,9 @@ +features: +- name: constraint-validation + files: + - select-setcustomvalidity.html + - select-validity.html + - select-willvalidate-readonly-attribute.html +- name: show-picker-select + files: + - show-picker-*
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html index 2fb11ba..8b06212 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/stylable-select/select-keyboard-behavior.tentative.html
@@ -1,4 +1,5 @@ <!DOCTYPE html> +<meta name=timeout content=long> <link rel=author href="mailto:jarhar@chromium.org"> <link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1422275"> <link rel=help href="https://github.com/openui/open-ui/issues/433#issuecomment-1452461404"> @@ -68,6 +69,7 @@ async function closeListbox() { await test_driver.click(select); + await new Promise(requestAnimationFrame); } function addCloseCleanup(t) { @@ -96,6 +98,7 @@ assert_false(select.matches(':open'), 'The select should initially be closed.'); await test_driver.send_keys(document.activeElement, Space); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'The select should be open after pressing space.'); }, `${id}: When the listbox is closed, spacebar should open the listbox.`); @@ -108,6 +111,7 @@ 'The select should initially be closed.'); await test_driver.send_keys(document.activeElement, ArrowLeft); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'Arrow left should open the listbox.'); assert_equals(select.value, 'two', @@ -115,6 +119,7 @@ await closeListbox(); await test_driver.send_keys(document.activeElement, ArrowUp); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'Arrow up should open the listbox.'); assert_equals(select.value, 'two', @@ -122,6 +127,7 @@ await closeListbox(); await test_driver.send_keys(document.activeElement, ArrowRight); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'Arrow right should open the listbox.'); assert_equals(select.value, 'two', @@ -129,6 +135,7 @@ await closeListbox(); await test_driver.send_keys(document.activeElement, ArrowDown); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'Arrow down should open the listbox.'); assert_equals(select.value, 'two', @@ -147,6 +154,7 @@ } else { await test_driver.send_keys(select, Enter); } + await new Promise(requestAnimationFrame); assert_false(select.matches(':open'), 'Enter should not open the listbox when outside a form.'); @@ -161,6 +169,7 @@ } else { await test_driver.send_keys(select, Enter); } + await new Promise(requestAnimationFrame); assert_true(formWasSubmitted, 'Enter should submit the form when the listbox is closed.'); assert_false(select.matches(':open'), @@ -175,30 +184,35 @@ select.value = 'two'; await test_driver.click(select); + await new Promise(requestAnimationFrame); assert_true(select.matches(':open'), 'The select should open when clicked.'); assert_equals(document.activeElement, optionTwo, 'The selected option should receive initial focus.'); await test_driver.send_keys(document.activeElement, ArrowDown); + await new Promise(requestAnimationFrame); assert_equals(document.activeElement, optionThree, 'The next option should receive focus when the down arrow key is pressed.'); assert_equals(select.value, 'two', 'The selects value should not change when focusing another option.'); await test_driver.send_keys(document.activeElement, ArrowUp); + await new Promise(requestAnimationFrame); assert_equals(document.activeElement, optionTwo, 'The previous option should receive focus when the up arrow key is pressed.'); assert_equals(select.value, 'two', 'The selects value should not change when focusing another option.'); await test_driver.send_keys(document.activeElement, ArrowUp); + await new Promise(requestAnimationFrame); assert_equals(document.activeElement, optionOne, 'The first option should be selected.'); assert_equals(select.value, 'two', 'The selects value should not change when focusing another option.'); await test_driver.send_keys(document.activeElement, Enter); + await new Promise(requestAnimationFrame); assert_false(select.matches(':open'), 'The listbox should be closed after pressing enter.'); assert_equals(select.value, 'one',
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/WEB_FEATURES.yml new file mode 100644 index 0000000..14479d4b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-textarea-element/WEB_FEATURES.yml
@@ -0,0 +1,6 @@ +features: +- name: constraint-validation + files: + - textarea-setcustomvalidity.html + - textarea-validity-clone.html + - textarea-validity-valueMissing-inside-datalist.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/WEB_FEATURES.yml new file mode 100644 index 0000000..be3924a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/WEB_FEATURES.yml
@@ -0,0 +1,4 @@ +features: +- name: details-name + files: + - name-attribute.html
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/WEB_FEATURES.yml new file mode 100644 index 0000000..bd821885 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: template + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/WEB_FEATURES.yml new file mode 100644 index 0000000..604e049 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/selectors/pseudo-classes/WEB_FEATURES.yml
@@ -0,0 +1,7 @@ +features: +- name: autofill + files: + - autofill.html +- name: default + files: + - default.html
diff --git a/third_party/blink/web_tests/external/wpt/html/syntax/parsing/template/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/template/WEB_FEATURES.yml new file mode 100644 index 0000000..bd821885 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/template/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: template + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/WEB_FEATURES.yml new file mode 100644 index 0000000..423a469b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/webappapis/structured-clone/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: structured-clone + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/resources/testharnessreport.js b/third_party/blink/web_tests/external/wpt/resources/testharnessreport.js index e5cb40fe..405a2d8 100644 --- a/third_party/blink/web_tests/external/wpt/resources/testharnessreport.js +++ b/third_party/blink/web_tests/external/wpt/resources/testharnessreport.js
@@ -14,31 +14,6 @@ * parameters they are called with see testharness.js */ -function dump_test_results(tests, status) { - var results_element = document.createElement("script"); - results_element.type = "text/json"; - results_element.id = "__testharness__results__"; - var test_results = tests.map(function(x) { - return {name:x.name, status:x.status, message:x.message, stack:x.stack} - }); - var data = {test:window.location.href, - tests:test_results, - status: status.status, - message: status.message, - stack: status.stack}; - results_element.textContent = JSON.stringify(data); - - // To avoid a HierarchyRequestError with XML documents, ensure that 'results_element' - // is inserted at a location that results in a valid document. - var parent = document.body - ? document.body // <body> is required in XHTML documents - : document.documentElement; // fallback for optional <body> in HTML5, SVG, etc. - - parent.appendChild(results_element); -} - -add_completion_callback(dump_test_results); - /* If the parent window has a testharness_properties object, * we use this to provide the test settings. This is used by the * default in-browser runner to configure the timeout and the
diff --git a/third_party/blink/web_tests/fast/block/float/float-in-float-hit-testing-expected.txt b/third_party/blink/web_tests/fast/block/float/float-in-float-hit-testing-expected.txt new file mode 100644 index 0000000..dd064d8 --- /dev/null +++ b/third_party/blink/web_tests/fast/block/float/float-in-float-hit-testing-expected.txt
@@ -0,0 +1 @@ +CONSOLE MESSAGE: A soft navigation has been detected: float-in-float-hit-testing.html#
diff --git a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-click-on-inline-continations-expected.txt b/third_party/blink/web_tests/fast/events/touch/gesture/gesture-click-on-inline-continations-expected.txt index c5a48cc..b4c2667 100644 --- a/third_party/blink/web_tests/fast/events/touch/gesture/gesture-click-on-inline-continations-expected.txt +++ b/third_party/blink/web_tests/fast/events/touch/gesture/gesture-click-on-inline-continations-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE MESSAGE: A soft navigation has been detected: gesture-click-on-inline-continations.html# The test succeeds if this does not hang or crash when getting the y conner's position from inline renderer. This test passes if it does not timeout. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/forms/access-key-expected.txt b/third_party/blink/web_tests/fast/forms/access-key-expected.txt index e1685bb6..e6c25557 100644 --- a/third_party/blink/web_tests/fast/forms/access-key-expected.txt +++ b/third_party/blink/web_tests/fast/forms/access-key-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE MESSAGE: A soft navigation has been detected: access-key.html# This test checks to see if accesskey attributes works on the specified elements. If this test passes you should see 1 - 9 and a, b and c clicked or focussed.
diff --git a/third_party/blink/web_tests/hittesting/text-overflow-inline-image-expected.txt b/third_party/blink/web_tests/hittesting/text-overflow-inline-image-expected.txt index b1f318bb..13ee25ba 100644 --- a/third_party/blink/web_tests/hittesting/text-overflow-inline-image-expected.txt +++ b/third_party/blink/web_tests/hittesting/text-overflow-inline-image-expected.txt
@@ -1,3 +1,4 @@ +CONSOLE MESSAGE: A soft navigation has been detected: text-overflow-inline-image.html# this is a link clicked
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-hit-testing-expected.txt b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-hit-testing-expected.txt new file mode 100644 index 0000000..a096403 --- /dev/null +++ b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/float-in-float-hit-testing-expected.txt
@@ -0,0 +1 @@ +CONSOLE MESSAGE: A soft navigation has been detected: http://127.0.0.1:8000/third_party/blink/web_tests/fast/block/float/float-in-float-hit-testing.html#
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt deleted file mode 100644 index 0594c46..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -[FAIL] matmul float32 2D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 3D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 4D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 3D (broadcast) tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 4D (broadcast) tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 3D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 5D and 5D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 5D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt deleted file mode 100644 index 0594c46..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/webnn-service-without-gpu/external/wpt/webnn/conformance_tests/gpu/matmul.https.any.worker-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -This is a testharness.js-based test. -[FAIL] matmul float32 2D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 3D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 4D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 3D (broadcast) tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 3D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 4D (broadcast) tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 4D and 3D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 5D and 5D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -[FAIL] matmul float32 5D and 2D tensors - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': matmul is not implemented" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt new file mode 100644 index 0000000..88c5f7b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt
@@ -0,0 +1,68 @@ +This is a testharness.js-based test. +Found 32 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] abs float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 0D scalar + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 0D scalar + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt new file mode 100644 index 0000000..88c5f7b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac14-arm64/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt
@@ -0,0 +1,68 @@ +This is a testharness.js-based test. +Found 32 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] abs float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] abs float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 0D scalar + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] identity float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] log float32 positive 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] neg float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 0D scalar + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 1D constant tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 1D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 2D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 3D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 4D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +[FAIL] reciprocal float32 5D tensor + promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt index 149ac59..5d481135 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 82 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 64 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] abs float32 1D constant tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] abs float32 1D tensor @@ -13,67 +13,41 @@ [FAIL] abs float32 5D tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] ceil float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] cos float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 0D scalar - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] exp float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] identity float32 0D scalar promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] identity float32 1D constant tensor @@ -127,42 +101,32 @@ [FAIL] reciprocal float32 5D tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] sin float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sqrt float32 0D scalar - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2 should be close enough to expected 2.001115560531616 by the acceptable 1 ULP distance, but they have 4679 ULP distance expected true got false [FAIL] sqrt float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] tan float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test tan float32 property 0, expected -0.8582430481910706 +/- 0.0009765625, expected -0.8582430481910706 but got -0.8763164281845093 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt index 149ac59..5d481135 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/gpu/elementwise_unary.https.any.worker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 82 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 64 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] abs float32 1D constant tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] abs float32 1D tensor @@ -13,67 +13,41 @@ [FAIL] abs float32 5D tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] ceil float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] ceil float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test ceil float32 actual 5 should be close enough to expected 6 by the acceptable 0 ULP distance, but they have 2097152 ULP distance expected true got false [FAIL] cos float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] cos float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 0D scalar - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] erf float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test cos float32 property 1, expected 0.43789437413215637 +/- 0.0009765625, expected 0.43789437413215637 but got 0.443359375 [FAIL] exp float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] exp float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] floor float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test exp float32 actual 1.4072265625 should be close enough to expected 1.4079625606536865 by the acceptable 32 ULP distance, but they have 6174 ULP distance expected true got false [FAIL] identity float32 0D scalar promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] identity float32 1D constant tensor @@ -127,42 +101,32 @@ [FAIL] reciprocal float32 5D tensor promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." [FAIL] sin float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sin float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test sin float32 property 0, expected -0.946033775806427 +/- 0.0009765625, expected -0.946033775806427 but got -0.935546875 [FAIL] sqrt float32 0D scalar - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2 should be close enough to expected 2.001115560531616 by the acceptable 1 ULP distance, but they have 4679 ULP distance expected true got false [FAIL] sqrt float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] sqrt float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_true: assert_array_approx_equals_ulp: test sqrt float32 actual 2.69140625 should be close enough to expected 2.693697690963745 by the acceptable 1 ULP distance, but they have 9611 ULP distance expected true got false [FAIL] tan float32 1D constant tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 1D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 2D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 3D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 4D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." -[FAIL] tan float32 5D tensor - promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'build' on 'MLGraphBuilder': Unimplemented Unary Operator." + assert_array_approx_equals: test tan float32 property 0, expected -0.8582430481910706 +/- 0.0009765625, expected -0.8582430481910706 but got -0.8763164281845093 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt index 0f99026..05eac7c 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -1210,13 +1210,7 @@ property volume property webkitAudioDecodedByteCount property webkitDecodedFrameCount - property webkitDisplayingFullscreen property webkitDroppedFrameCount - property webkitEnterFullScreen - property webkitEnterFullscreen - property webkitExitFullScreen - property webkitExitFullscreen - property webkitSupportsFullscreen property webkitVideoDecodedByteCount property width html element wbr
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 18ab9a77..c5acdbd7 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4632,19 +4632,13 @@ getter videoHeight getter videoWidth getter webkitDecodedFrameCount - getter webkitDisplayingFullscreen getter webkitDroppedFrameCount - getter webkitSupportsFullscreen getter width method cancelVideoFrameCallback method constructor method getVideoPlaybackQuality method requestPictureInPicture method requestVideoFrameCallback - method webkitEnterFullScreen - method webkitEnterFullscreen - method webkitExitFullScreen - method webkitExitFullscreen setter disablePictureInPicture setter height setter onenterpictureinpicture
diff --git a/third_party/chromite b/third_party/chromite index 8af9063..3db9d50 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit 8af906338f6c07813067abf296170c8a4f46c538 +Subproject commit 3db9d50f201adfc9c0e567d8c7c763f91231579f
diff --git a/third_party/cloud_authenticator/processor/src/lib.rs b/third_party/cloud_authenticator/processor/src/lib.rs index 81a1dd7d..380d8a28 100644 --- a/third_party/cloud_authenticator/processor/src/lib.rs +++ b/third_party/cloud_authenticator/processor/src/lib.rs
@@ -1690,26 +1690,28 @@ assert_eq!(pin_state.generation_high_water, 1); assert_eq!(pin_state.attempts, 0); - // The wrong PIN three times in a row should lock the device. + // The wrong PIN five times in a row should lock the device. + let (_error, _pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); + let (_error, _pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); let (_error, _pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); let (_error, _pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); let (error, pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); assert_eq!(error, Some(Value::Int(3))); assert_eq!(pin_state.generation_high_water, 1); - assert_eq!(pin_state.attempts, 3); + assert_eq!(pin_state.attempts, 5); // Now the wrong PIN will generate a different error and not increment the // counter. let (error, pin_state, state) = attempt_pin(state, &wrapped_pin_data, &wrong_pin_claim); assert_eq!(error, Some(Value::Int(4))); assert_eq!(pin_state.generation_high_water, 1); - assert_eq!(pin_state.attempts, 3); + assert_eq!(pin_state.attempts, 5); // And so will the correct PIN. let (error, pin_state, _state) = attempt_pin(state, &wrapped_pin_data, &pin_claim); assert_eq!(error, Some(Value::Int(4))); assert_eq!(pin_state.generation_high_water, 1); - assert_eq!(pin_state.attempts, 3); + assert_eq!(pin_state.attempts, 5); } #[test]
diff --git a/third_party/cloud_authenticator/processor/src/passkeys.rs b/third_party/cloud_authenticator/processor/src/passkeys.rs index 1724c8b..a17a9367 100644 --- a/third_party/cloud_authenticator/processor/src/passkeys.rs +++ b/third_party/cloud_authenticator/processor/src/passkeys.rs
@@ -76,7 +76,7 @@ // The number of incorrect PIN attempts before further PIN attempts will be // denied. -const MAX_PIN_ATTEMPTS: i64 = 3; +const MAX_PIN_ATTEMPTS: i64 = 5; fn key(k: &str) -> MapKey { MapKey::String(String::from(k))
diff --git a/third_party/depot_tools b/third_party/depot_tools index 6aaae85..1a61eb6 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 6aaae85821254406042a11254d49b14c9d1b44f3 +Subproject commit 1a61eb625d4b062bb2d6f0902b4979b48def4d33
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index b70ff80..2829e05 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit b70ff80eb2b57e077d19ced22f77faf61212b7c0 +Subproject commit 2829e054a8419e6ecf6d60eb321ca8511317d3f2
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 1b37ee5..6a303cb 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 1b37ee54c6d14d87ca3aa3e38b9fd65957fc162f +Subproject commit 6a303cbb86cd070e504f3728d314430f17b4e53d
diff --git a/third_party/fuzztest/BUILD.gn b/third_party/fuzztest/BUILD.gn index df4f2d8..66818ede 100644 --- a/third_party/fuzztest/BUILD.gn +++ b/third_party/fuzztest/BUILD.gn
@@ -346,9 +346,8 @@ deps += [ "//testing/libfuzzer:fuzzing_engine_no_main" ] } public_deps = [ ":fuzztest_internal" ] - public_configs = [ ":fuzztest_internal_config" ] configs -= fuzztest_remove_configs - configs += fuzztest_add_configs + configs += fuzztest_add_configs + [ ":fuzztest_internal_config" ] testonly = true }
diff --git a/third_party/inspector_protocol/crdtp/chromium/protocol_traits.cc b/third_party/inspector_protocol/crdtp/chromium/protocol_traits.cc index ac3d525..859014b0 100644 --- a/third_party/inspector_protocol/crdtp/chromium/protocol_traits.cc +++ b/third_party/inspector_protocol/crdtp/chromium/protocol_traits.cc
@@ -23,8 +23,7 @@ } std::string Binary::toBase64() const { - return base::Base64Encode(base::StringPiece( - reinterpret_cast<const char*>(bytes_->front()), bytes_->size())); + return base::Base64Encode(base::as_string_view(*bytes_)); } // static @@ -41,7 +40,7 @@ // static Binary Binary::fromVector(std::vector<uint8_t> data) { - return Binary(base::RefCountedBytes::TakeVector(&data)); + return Binary(base::MakeRefCounted<base::RefCountedBytes>(std::move(data))); } // static
diff --git a/third_party/inspector_protocol/crdtp/chromium/protocol_traits.h b/third_party/inspector_protocol/crdtp/chromium/protocol_traits.h index 3633431..480b5b2 100644 --- a/third_party/inspector_protocol/crdtp/chromium/protocol_traits.h +++ b/third_party/inspector_protocol/crdtp/chromium/protocol_traits.h
@@ -94,8 +94,15 @@ // Implements Serializable. void AppendSerialized(std::vector<uint8_t>* out) const override; - const uint8_t* data() const { return bytes_->front(); } + // Allow explicit conversion to `base::span`. + const uint8_t* data() const { return bytes_->data(); } size_t size() const { return bytes_->size(); } + // data()/size() provide access to Binary's data as a span, but each one + // requires a virtual call. Like RefCountedData, provide this operator as an + // optimization. + explicit operator base::span<const uint8_t>() const { + return base::span(*bytes_); + } scoped_refptr<base::RefCountedMemory> bytes() const { return bytes_; } std::string toBase64() const;
diff --git a/third_party/jni_zero/codegen/called_by_native_header.py b/third_party/jni_zero/codegen/called_by_native_header.py index a92cfbf4..24a533c 100644 --- a/third_party/jni_zero/codegen/called_by_native_header.py +++ b/third_party/jni_zero/codegen/called_by_native_header.py
@@ -43,16 +43,21 @@ return f'const jni_zero::JavaRef<{ret}>&' -def _param_expression_cpp(param): - if converted_type := param.java_type.converted_type(): - name = f'{param.name}_converted' - else: - name = param.name - if param.java_type.is_primitive(): - if param.java_type.primitive_name == 'int' and not converted_type: - return f'as_jint({name})' - return name - return f'{name}.obj()' +def _prep_param(sb, param): + """Returns the snippet to use for the parameter.""" + orig_name = param.cpp_name() + java_type = param.java_type + + if converted_type := java_type.converted_type(): + converted_name = f'converted_{param.name}' + convert_type.to_jni_assignment(sb, converted_name, orig_name, java_type) + orig_name = converted_name + + if java_type.is_primitive(): + if java_type.primitive_name == 'int' and not converted_type: + return f'as_jint({orig_name})' + return orig_name + return f'{orig_name}.obj()' def _jni_function_name(called_by_native): @@ -86,7 +91,8 @@ plist.append('JNIEnv* env') if not reciever_arg_is_class: plist.append('const jni_zero::JavaRef<jobject>& obj') - plist.extend(f'{_param_type_cpp(p.java_type)} {p.name}' for p in cbn.params) + plist.extend(f'{_param_type_cpp(p.java_type)} {p.cpp_name()}' + for p in cbn.params) with sb.block(): sb('static std::atomic<jmethodID> cached_method_id(nullptr);\n') @@ -110,37 +116,34 @@ '&cached_method_id' ]) - for param in cbn.params: - if converted_type := param.java_type.converted_type(): - convert_type.to_jni_assignment(sb, f'{param.name}_converted', - param.name, param.java_type) + param_rvalues = [_prep_param(sb, p) for p in cbn.params] if not is_void: - return_rvalue = 'ret' - sb(f'auto ret = ') + return_rvalue = '_ret' + sb(f'auto _ret = ') with sb.statement(): sb(f'env->{_jni_function_name(cbn)}') - with sb.param_list() as plist: - plist += [receiver_arg, 'call_context.method_id()'] - plist.extend(_param_expression_cpp(p) for p in cbn.params) + sb.param_list([receiver_arg, 'call_context.method_id()'] + param_rvalues) if not is_void: - if not return_type.is_primitive(): - jobject_type = return_type.to_cpp() - if jobject_type != 'jobject': - return_rvalue = 'ret2' - sb(f'{jobject_type} ret2 = static_cast<{jobject_type}>(ret);\n') + if return_type.is_primitive() or return_type.converted_type(): + with sb.statement(): + sb('return ') + if return_type.converted_type(): + convert_type.from_jni_expression(sb, return_rvalue, return_type) + else: + sb(return_rvalue) + return + + jobject_type = return_type.to_cpp() + if jobject_type != 'jobject': + return_rvalue = '_ret2' + sb(f'{jobject_type} _ret2 = static_cast<{jobject_type}>(_ret);\n') with sb.statement(): - sb('return ') - if return_type.converted_type(): - convert_type.from_jni_expression(sb, return_rvalue, return_type) - elif not return_type.is_primitive(): - sb(f'jni_zero::ScopedJavaLocalRef<{jobject_type}>(env, ' - f'{return_rvalue})') - else: - sb(return_rvalue) + sb(f'return jni_zero::ScopedJavaLocalRef<{jobject_type}>(env, ' + f'{return_rvalue})') def methods(called_by_natives):
diff --git a/third_party/jni_zero/codegen/convert_type.py b/third_party/jni_zero/codegen/convert_type.py index 9cb41b7..a6ad44a 100644 --- a/third_party/jni_zero/codegen/convert_type.py +++ b/third_party/jni_zero/codegen/convert_type.py
@@ -11,15 +11,13 @@ declarations = set() for java_type in java_to_cpp_types: T = java_type.converted_type() - J = java_type.to_cpp() declarations.add(f'template<> {T} ' - f'FromJniType<{T}, {J}>(JNIEnv*, const JavaRef<{J}>&);') + f'FromJniType<{T}>(JNIEnv*, const JavaRef<jobject>&);') for java_type in cpp_to_java_types: T = java_type.converted_type() - J = java_type.to_cpp() - declarations.add(f'template<> jni_zero::ScopedJavaLocalRef<{J}> ' - f'ToJniType<{T}, {J}>(JNIEnv*, {T} const&);') + declarations.add(f'template<> jni_zero::ScopedJavaLocalRef<jobject> ' + f'ToJniType<{T}>(JNIEnv*, {T} const&);') if not declarations: return '' @@ -35,16 +33,21 @@ def to_jni_expression(sb, rvalue, java_type, clazz_param=None): - """Returns a conversion call expression from specified @JniType to default jni type.""" + """Writes a ToJniType() expression to |sb|. + + Args: + rvalue: Snippet to use as input to ToJniType(). + java_type: Type containing the @JniType annotation. + clazz_param: Snippet to use as the third parameter for array conversions. + """ + T = java_type.converted_type() + assert T if java_type.is_primitive(): - if java_type.primitive_name == 'int' and not java_type.converted_type(): - rvalue = f'as_jint({rvalue})' sb(f'static_cast<{java_type.to_cpp()}>({rvalue})') return - T = java_type.converted_type() if not java_type.is_array(): - sb(f'jni_zero::ToJniType<{T}, {java_type.to_cpp()}>') + sb(f'jni_zero::ToJniType<{T}>') sb.param_list(['env', rvalue]) return @@ -53,65 +56,53 @@ raise Exception( '@JniType() for multi-dimensional arrays are not yet supported. ' 'Found ' + T) - if element_type.is_primitive(): - sb(f'jni_zero::ConvertArray<{T}>::ToJniType') - sb.param_list(['env', rvalue]) - return - - if clazz_param: - clazz_expr = clazz_param.name - else: - clazz_expr = header_common.class_accessor_expression( - element_type.java_class) - J = element_type.to_cpp() - sb(f'jni_zero::ConvertArray<{T}>::ToJniType<{J}>') - sb.param_list(['env', rvalue, clazz_expr]) + sb(f'jni_zero::ConvertArray<{T}>::ToJniType') + with sb.param_list() as plist: + plist += ['env', rvalue] + if not element_type.is_primitive(): + if clazz_param: + plist += [clazz_param.name] + else: + plist += [ + header_common.class_accessor_expression(element_type.java_class) + ] def to_jni_assignment(sb, dest_var_name, src_var_name, java_type): - """Returns a conversion statement from specified @JniType to default jni type.""" + """Writes a ToJniType() assignment to |sb|.""" with sb.statement(): if java_type.is_primitive(): var_type = java_type.to_cpp() else: - var_type = f'jni_zero::ScopedJavaLocalRef<{java_type.to_cpp()}>' + var_type = f'jni_zero::ScopedJavaLocalRef<jobject>' sb(f'{var_type} {dest_var_name} = ') to_jni_expression(sb, src_var_name, java_type) def from_jni_expression(sb, rvalue, java_type): - """Returns a conversion call expression from default jni type to specified @JniType.""" + """Writes a FromJniType() expression to |sb|. + + Args: + rvalue: Snippet to use as input to FromJniType(). + java_type: Type containing the @JniType annotation. + """ T = java_type.converted_type() - J = java_type.to_cpp() + assert T if java_type.is_primitive(): sb(f'static_cast<{T}>({rvalue})') return - if not java_type.is_primitive(): - rvalue = header_common.java_param_ref_expression(J, rvalue) + jtype = java_type.to_cpp() if java_type.is_array() else 'jobject' + rvalue = f'jni_zero::JavaParamRef<{jtype}>(env, {rvalue})' if not java_type.is_array(): - sb(f'jni_zero::FromJniType<{T}, {J}>') + sb(f'jni_zero::FromJniType<{T}>') sb.param_list(['env', rvalue]) return - element_type = java_type.to_array_element_type() - if element_type.is_array(): + if java_type.array_dimensions > 1: raise Exception( '@JniType() for multi-dimensional arrays are not yet supported. ' 'Found ' + T) - if element_type.is_primitive(): - sb(f'jni_zero::ConvertArray<{T}>::FromJniType') - sb.param_list(['env', rvalue]) - return - - J = java_type.to_array_element_type().to_cpp() - sb(f'jni_zero::ConvertArray<{T}>::FromJniType<{J}>') + sb(f'jni_zero::ConvertArray<{T}>::FromJniType') sb.param_list(['env', rvalue]) - - -def from_jni_assignment(sb, dst_var_name, src_var_name, java_type): - """Returns a conversion statement from default jni type to specified @JniType.""" - with sb.statement(): - sb(f'{java_type.converted_type()} {dst_var_name} = ') - from_jni_expression(sb, src_var_name, java_type)
diff --git a/third_party/jni_zero/codegen/header_common.py b/third_party/jni_zero/codegen/header_common.py index be0ee6ca..40a84eb 100644 --- a/third_party/jni_zero/codegen/header_common.py +++ b/third_party/jni_zero/codegen/header_common.py
@@ -73,7 +73,3 @@ #endif // {header_guard} """ return preamble, epilogue - - -def java_param_ref_expression(c_type, name): - return f'jni_zero::JavaParamRef<{c_type}>(env, {name})'
diff --git a/third_party/jni_zero/codegen/natives_header.py b/third_party/jni_zero/codegen/natives_header.py index b802192..63bcaaac 100644 --- a/third_party/jni_zero/codegen/natives_header.py +++ b/third_party/jni_zero/codegen/natives_header.py
@@ -37,23 +37,8 @@ plist.append('JNIEnv* env') if not native.static: plist.append('const jni_zero::JavaParamRef<jobject>& jcaller') - plist.extend(f'{_param_type_cpp(p.java_type)} {p.name}' for p in params) - - -def _impl_call_params(sb, native, params): - with sb.param_list() as plist: - plist.append('env') - if not native.static: - plist.append(header_common.java_param_ref_expression( - 'jobject', 'jcaller')) - for p in params: - if p.java_type.converted_type(): - plist.append(f'{p.name}_converted') - elif p.java_type.is_primitive(): - plist.append(p.name) - else: - c_type = p.java_type.to_cpp() - plist.append(header_common.java_param_ref_expression(c_type, p.name)) + plist.extend(f'{_param_type_cpp(p.java_type)} {p.cpp_name()}' + for p in params) def proxy_declaration(sb, jni_obj, native): @@ -64,18 +49,41 @@ plist.append('JNIEnv* env') jtype = 'jclass' if native.static else 'jobject' plist.append(f'{jtype} jcaller') - plist.extend(f'{p.java_type.to_cpp()} {p.name}' + plist.extend(f'{p.java_type.to_cpp()} {p.cpp_name()}' for p in native.proxy_params) +def _prep_param(sb, param, proxy_type): + """Returns the snippet to use for the parameter.""" + orig_name = param.cpp_name() + java_type = param.java_type + + if java_type.converted_type(): + ret = f'{param.name}_converted' + with sb.statement(): + sb(f'{java_type.converted_type()} {ret} = ') + if java_type.is_array(): + orig_name = f'static_cast<{java_type.to_cpp()}>({orig_name})' + convert_type.from_jni_expression(sb, orig_name, java_type) + return ret + + if java_type.is_primitive(): + return orig_name + + if java_type.to_cpp() != proxy_type.to_cpp(): + # E.g. jobject -> jstring + orig_name = f'static_cast<{java_type.to_cpp()}>({orig_name})' + return f'jni_zero::JavaParamRef<{java_type.to_cpp()}>(env, {orig_name})' + + def _single_method(sb, jni_obj, native): cpp_class = native.first_param_cpp_type if cpp_class: - params = native.proxy_params[1:] + proxy_params = native.proxy_params[1:] + params = native.params[1:] else: - params = native.proxy_params - if native.needs_implicit_array_element_class_param: - params = params[:-1] + proxy_params = native.proxy_params + params = native.params # Only non-class methods need to be forward-declared. if not cpp_class: @@ -83,46 +91,64 @@ sb('\n') proxy_declaration(sb, jni_obj, native) + proxy_return_type = native.proxy_return_type + return_type = native.return_type with sb.block(): if cpp_class: + first_param_name = native.params[0].cpp_name() sb(f"""\ -{cpp_class}* native = reinterpret_cast<{cpp_class}*>({native.params[0].name}); -CHECK_NATIVE_PTR(env, jcaller, native, "{native.cpp_name}\"""") - if default_value := native.return_type.to_cpp_default_value(): +{cpp_class}* _native = reinterpret_cast<{cpp_class}*>({first_param_name}); +CHECK_NATIVE_PTR(env, jcaller, _native, "{native.cpp_name}\"""") + if default_value := proxy_return_type.to_cpp_default_value(): sb(f', {default_value}') sb(')\n') - for p in params: - if p.java_type.converted_type(): - convert_type.from_jni_assignment(sb, f'{p.name}_converted', p.name, - p.java_type) + param_rvalues = [ + _prep_param(sb, param, proxy_param.java_type) + for param, proxy_param in zip(params, proxy_params) + ] with sb.statement(): - if not native.return_type.is_void(): - sb('auto ret = ') + if not return_type.is_void(): + sb('auto _ret = ') if cpp_class: - sb(f'native->{native.cpp_name}') + sb(f'_native->{native.cpp_name}') else: sb(f'{native.cpp_impl_name}') - _impl_call_params(sb, native, params) + with sb.param_list() as plist: + plist.append('env') + if not native.static: + plist.append('jni_zero::JavaParamRef<jobject>(env, jcaller)') + plist.extend(param_rvalues) - if not native.return_type.is_void(): + if return_type.is_void(): + return + + if not return_type.converted_type(): with sb.statement(): - sb('return ') - if native.return_type.converted_type(): - if native.needs_implicit_array_element_class_param: - clazz_param = native.proxy_params[-1] - else: - clazz_param = None - convert_type.to_jni_expression(sb, - 'ret', - native.return_type, - clazz_param=clazz_param) - else: - sb('ret') - - if not native.return_type.is_primitive(): + sb('return _ret') + if not return_type.is_primitive(): sb('.Release()') + return + + with sb.statement(): + sb('jobject converted_ret = ') + if native.needs_implicit_array_element_class_param: + clazz_param = proxy_params[-1] + else: + clazz_param = None + convert_type.to_jni_expression(sb, + '_ret', + return_type, + clazz_param=clazz_param) + sb('.Release()') + + with sb.statement(): + sb('return ') + if proxy_return_type.to_cpp() != 'jobject': + sb(f'static_cast<{proxy_return_type.to_cpp()}>(converted_ret)') + else: + sb('converted_ret') def methods(jni_obj):
diff --git a/third_party/jni_zero/java_types.py b/third_party/jni_zero/java_types.py index 06708f7..d37020a 100644 --- a/third_party/jni_zero/java_types.py +++ b/third_party/jni_zero/java_types.py
@@ -265,6 +265,11 @@ """Converts to types used over JNI boundary.""" return JavaParam(self.java_type.to_proxy(), self.name) + def cpp_name(self): + if self.name in ('env', 'jcaller'): + return f'_{self.name}' + return self.name + class JavaParamList(tuple): """Represents a parameter list."""
diff --git a/third_party/jni_zero/jni_zero.cc b/third_party/jni_zero/jni_zero.cc index a78f7e16..dc34db5 100644 --- a/third_party/jni_zero/jni_zero.cc +++ b/third_party/jni_zero/jni_zero.cc
@@ -131,12 +131,6 @@ } } -jobject JavaRef<jobject>::ReleaseInternal() { - jobject obj = obj_; - obj_ = nullptr; - return obj; -} - JNIEnv* AttachCurrentThread() { JNI_ZERO_DCHECK(g_jvm); JNIEnv* env = nullptr;
diff --git a/third_party/jni_zero/jni_zero.h b/third_party/jni_zero/jni_zero.h index acbcfb14..b177d1c 100644 --- a/third_party/jni_zero/jni_zero.h +++ b/third_party/jni_zero/jni_zero.h
@@ -157,7 +157,12 @@ void SetNewGlobalRef(JNIEnv* env, jobject obj); void ResetLocalRef(JNIEnv* env); void ResetGlobalRef(); - jobject ReleaseInternal(); + + jobject ReleaseInternal() { + jobject obj = obj_; + obj_ = nullptr; + return obj; + } private: jobject obj_ = nullptr; @@ -709,11 +714,11 @@ // Primary templates for non-Array conversion fuctions. Embedding application // can specialize these functions for their own custom types in order to use // custom types in @JniType. -template <typename T, typename J = jobject> -T FromJniType(JNIEnv*, const JavaRef<J>&); +template <typename T> +T FromJniType(JNIEnv*, const JavaRef<jobject>&); -template <typename T, typename J = jobject> -ScopedJavaLocalRef<J> ToJniType(JNIEnv*, const T&); +template <typename T> +ScopedJavaLocalRef<jobject> ToJniType(JNIEnv*, const T&); // Primary template for Array conversion. // This is in a struct so that we are able to write a default implementation for @@ -736,18 +741,12 @@ concept has_insert = requires(T t, T::value_type v) { t.insert(v); }; template <typename T> -concept is_range = requires(T t) { +concept is_container = requires(T t) { T::value_type; { t.begin() } -> std::same_as<typename T::const_iterator>; { t.end() } -> std::same_as<typename T::const_iterator>; { t.size() } -> std::same_as<size_t>; }; - -template <typename T> -concept is_container = requires(T t) { - is_range<T>; - requires has_push_back<T> || has_insert<T>; -}; } // namespace internal // Partial specialization for converting java arrays into std containers @@ -758,41 +757,29 @@ } struct ConvertArray<ContainerType> { private: - using ElementType = ContainerType::value_type; + using ElementType = std::remove_const_t<typename ContainerType::value_type>; - template <typename JniType = jobject> - static ElementType ElementFromJniType(JNIEnv* env, - const JavaRef<JniType>& j_element) { - if constexpr (std::same_as<ElementType, ScopedJavaLocalRef<JniType>>) { - return j_element; - } else { - return jni_zero::FromJniType<ElementType, JniType>(env, j_element); - } - } - - template <typename JniType = jobject> - static ScopedJavaLocalRef<JniType> ElementToJniType( + static ScopedJavaLocalRef<jobject> ElementToJniType( JNIEnv* env, const ElementType& element) { - if constexpr (std::same_as<ElementType, ScopedJavaLocalRef<JniType>>) { - return element; - } else if constexpr (std::is_pointer_v<ElementType> && - !std::is_fundamental_v< - std::remove_pointer_t<ElementType>>) { + if constexpr (std::is_pointer_v<ElementType> && + !std::is_fundamental_v<std::remove_pointer_t<ElementType>>) { // Dereference object pointers to enable using vector<ContainerType*> // in order to avoid copying objects for the sake of JNI. return jni_zero::ToJniType< - std::remove_const_t<std::remove_pointer_t<ElementType>>, JniType>( - env, *element); + std::remove_const_t<std::remove_pointer_t<ElementType>>>(env, + *element); } else { - return jni_zero::ToJniType<ElementType, JniType>(env, element); + return jni_zero::ToJniType<ElementType>(env, element); } } public: - template <typename JniType = jobject> static ContainerType FromJniType(JNIEnv* env, const JavaRef<jobjectArray>& j_array) { + constexpr bool has_push_back = internal::has_push_back<ContainerType>; + constexpr bool has_insert = internal::has_insert<ContainerType>; + static_assert(has_push_back || has_insert, "Template type not supported."); jsize array_jsize = env->GetArrayLength(j_array.obj()); ContainerType ret; @@ -801,20 +788,27 @@ ret.reserve(array_size); } for (jsize i = 0; i < array_jsize; ++i) { - ElementType element = ElementFromJniType<JniType>( - env, jni_zero::ScopedJavaLocalRef<JniType>::Adopt( - env, static_cast<JniType>( - env->GetObjectArrayElement(j_array.obj(), i)))); - if constexpr (internal::has_push_back<ContainerType>) { - ret.push_back(std::move(element)); + jobject j_element = env->GetObjectArrayElement(j_array.obj(), i); + // Do not call FromJniType for jobject->jobject. + if constexpr (std::is_base_of_v<JavaRef<jobject>, ElementType>) { + if constexpr (has_push_back) { + ret.emplace_back(env, j_element); + } else if constexpr (has_insert) { + ret.emplace(env, j_element); + } } else { - ret.insert(std::move(element)); + auto element = + jni_zero::ScopedJavaLocalRef<jobject>::Adopt(env, j_element); + if constexpr (has_push_back) { + ret.push_back(jni_zero::FromJniType<ElementType>(env, element)); + } else if constexpr (has_insert) { + ret.insert(jni_zero::FromJniType<ElementType>(env, element)); + } } } return ret; } - template <typename JniType = jobject> static ScopedJavaLocalRef<jobjectArray> ToJniType(JNIEnv* env, const ContainerType& collection, jclass clazz) { size_t array_size = collection.size(); @@ -825,11 +819,10 @@ jsize i = 0; for (auto& value : collection) { // Do not call ToJniType for jobject->jobject. - if constexpr (std::same_as<ElementType, ScopedJavaLocalRef<JniType>>) { + if constexpr (std::is_base_of_v<JavaRef<jobject>, ElementType>) { env->SetObjectArrayElement(j_array, i, value.obj()); } else { - ScopedJavaLocalRef<jobject> element = - ElementToJniType<JniType>(env, value); + ScopedJavaLocalRef<jobject> element = ElementToJniType(env, value); env->SetObjectArrayElement(j_array, i, element.obj()); } ++i;
diff --git a/third_party/jni_zero/test/golden/testBidirectionalClass-Final-GEN_JNI.java.golden b/third_party/jni_zero/test/golden/testBidirectionalClass-Final-GEN_JNI.java.golden index 0a6fb72..6d25d73 100644 --- a/third_party/jni_zero/test/golden/testBidirectionalClass-Final-GEN_JNI.java.golden +++ b/third_party/jni_zero/test/golden/testBidirectionalClass-Final-GEN_JNI.java.golden
@@ -18,19 +18,19 @@ // Hashed name: Java_J_N_MntihwyL public static native void org_jni_1zero_SampleForTests_destroy(long nativeCPPClass, Object caller, byte[] bytes); // Hashed name: Java_J_N_Ma__O3z2 - public static native Class org_jni_1zero_SampleForTests_getClass(Class arg0); + public static native Class org_jni_1zero_SampleForTests_getClass(Class env); // Hashed name: Java_J_N_MMoPH9HE - public static native double org_jni_1zero_SampleForTests_getDoubleFunction(Object caller); + public static native double org_jni_1zero_SampleForTests_getDoubleFunction(Object ret); // Hashed name: Java_J_N_MvEgj8y2 public static native float org_jni_1zero_SampleForTests_getFloatFunction(); // Hashed name: Java_J_N_Mz4j2yc1 public static native Object org_jni_1zero_SampleForTests_getMap(Object arg0); // Hashed name: Java_J_N_MyJgrTgs - public static native Object org_jni_1zero_SampleForTests_getNonPODDatatype(Object caller); + public static native Object org_jni_1zero_SampleForTests_getNonPODDatatype(Object jcaller); // Hashed name: Java_J_N_MOUT8MuQ public static native Throwable org_jni_1zero_SampleForTests_getThrowable(Throwable arg0); // Hashed name: Java_J_N_M$OcvYzW - public static native long org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType); + public static native long org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType, Object[] nonConvertedArray); // Hashed name: Java_J_N_M$SYxQqM public static native void org_jni_1zero_SampleForTests_iterateAndDoSomethingWithStructB(long nativeCPPClass, Object caller); // Hashed name: Java_J_N_MdXzE25W @@ -40,5 +40,5 @@ // Hashed name: Java_J_N_MUnVgmnP public static native String org_jni_1zero_SampleForTests_returnAString(long nativeCPPClass, Object caller); // Hashed name: Java_J_N_MtJ0n$3y - public static native void org_jni_1zero_SampleForTests_setNonPODDatatype(Object caller, Object rect); + public static native void org_jni_1zero_SampleForTests_setNonPODDatatype(Object obj, Object rect); }
diff --git a/third_party/jni_zero/test/golden/testBidirectionalClass-Placeholder-GEN_JNI.java.golden b/third_party/jni_zero/test/golden/testBidirectionalClass-Placeholder-GEN_JNI.java.golden index 42aae618..5f11b28 100644 --- a/third_party/jni_zero/test/golden/testBidirectionalClass-Placeholder-GEN_JNI.java.golden +++ b/third_party/jni_zero/test/golden/testBidirectionalClass-Placeholder-GEN_JNI.java.golden
@@ -10,16 +10,16 @@ public static native void org_jni_1zero_SampleForTests_addStructB(long nativeCPPClass, Object caller, Object b); public static native void org_jni_1zero_SampleForTests_destroy(long nativeCPPClass, Object caller, byte[] bytes); - public static native Class org_jni_1zero_SampleForTests_getClass(Class arg0); - public static native double org_jni_1zero_SampleForTests_getDoubleFunction(Object caller); + public static native Class org_jni_1zero_SampleForTests_getClass(Class env); + public static native double org_jni_1zero_SampleForTests_getDoubleFunction(Object ret); public static native float org_jni_1zero_SampleForTests_getFloatFunction(); public static native Object org_jni_1zero_SampleForTests_getMap(Object arg0); - public static native Object org_jni_1zero_SampleForTests_getNonPODDatatype(Object caller); + public static native Object org_jni_1zero_SampleForTests_getNonPODDatatype(Object jcaller); public static native Throwable org_jni_1zero_SampleForTests_getThrowable(Throwable arg0); - public static native long org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType); + public static native long org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType, Object[] nonConvertedArray); public static native void org_jni_1zero_SampleForTests_iterateAndDoSomethingWithStructB(long nativeCPPClass, Object caller); public static native int org_jni_1zero_SampleForTests_method(long nativeCPPClass, Object caller, String[] strings); public static native double org_jni_1zero_SampleForTests_methodOtherP0(long nativePtr, Object caller); public static native String org_jni_1zero_SampleForTests_returnAString(long nativeCPPClass, Object caller); - public static native void org_jni_1zero_SampleForTests_setNonPODDatatype(Object caller, Object rect); + public static native void org_jni_1zero_SampleForTests_setNonPODDatatype(Object obj, Object rect); }
diff --git a/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTestsJni.java.golden b/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTestsJni.java.golden index 3b7ff96..b2ce04f 100644 --- a/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTestsJni.java.golden +++ b/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTestsJni.java.golden
@@ -40,13 +40,13 @@ } @Override - public Class getClass(Class arg0) { - return (Class) GEN_JNI.org_jni_1zero_SampleForTests_getClass(arg0); + public Class getClass(Class env) { + return (Class) GEN_JNI.org_jni_1zero_SampleForTests_getClass(env); } @Override - public double getDoubleFunction(SampleForTests caller) { - return (double) GEN_JNI.org_jni_1zero_SampleForTests_getDoubleFunction(caller); + public double getDoubleFunction(SampleForTests ret) { + return (double) GEN_JNI.org_jni_1zero_SampleForTests_getDoubleFunction(ret); } @Override @@ -60,8 +60,8 @@ } @Override - public Object getNonPODDatatype(SampleForTests caller) { - return (Object) GEN_JNI.org_jni_1zero_SampleForTests_getNonPODDatatype(caller); + public Object getNonPODDatatype(SampleForTests jcaller) { + return (Object) GEN_JNI.org_jni_1zero_SampleForTests_getNonPODDatatype(jcaller); } @Override @@ -70,8 +70,8 @@ } @Override - public long init(SampleForTests caller, String param, byte[] bytes, SampleForTests convertedType) { - return (long) GEN_JNI.org_jni_1zero_SampleForTests_init(caller, param, bytes, convertedType); + public long init(SampleForTests caller, String param, byte[] bytes, SampleForTests convertedType, SampleForTests[] nonConvertedArray) { + return (long) GEN_JNI.org_jni_1zero_SampleForTests_init(caller, param, bytes, convertedType, nonConvertedArray); } @Override @@ -99,8 +99,8 @@ } @Override - public void setNonPODDatatype(SampleForTests caller, Rect rect) { - GEN_JNI.org_jni_1zero_SampleForTests_setNonPODDatatype(caller, rect); + public void setNonPODDatatype(SampleForTests obj, Rect rect) { + GEN_JNI.org_jni_1zero_SampleForTests_setNonPODDatatype(obj, rect); } public static SampleForTests.Natives get() {
diff --git a/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTests_jni.h.golden b/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTests_jni.h.golden index c54c8d2..5e1be992 100644 --- a/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTests_jni.h.golden +++ b/third_party/jni_zero/test/golden/testBidirectionalClass-SampleForTests_jni.h.golden
@@ -41,9 +41,9 @@ // Forward declare used conversion functions to avoid a compiler warning that // triggers if a conversion specialization exists within the including .cc file. namespace jni_zero { -template<> jni_zero::ScopedJavaLocalRef<jstring> ToJniType<const char*, jstring>(JNIEnv*, const char* const&); -template<> jni_zero::tests::CPPClass* FromJniType<jni_zero::tests::CPPClass*, jobject>(JNIEnv*, const JavaRef<jobject>&); -template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&); +template<> jni_zero::ScopedJavaLocalRef<jobject> ToJniType<const char*>(JNIEnv*, const char* const&); +template<> jni_zero::tests::CPPClass* FromJniType<jni_zero::tests::CPPClass*>(JNIEnv*, const JavaRef<jobject>&); +template<> std::string FromJniType<std::string>(JNIEnv*, const JavaRef<jobject>&); } // namespace jni_zero namespace jni_zero { namespace tests { @@ -54,9 +54,9 @@ jlong nativeCPPClass, jobject caller, jobject b) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB") - native->AddStructB( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "AddStructB") + _native->AddStructB( env, jni_zero::JavaParamRef<jobject>(env, caller), jni_zero::JavaParamRef<jobject>(env, b)); @@ -68,12 +68,12 @@ jlong nativeCPPClass, jobject caller, jbyteArray bytes) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "Destroy") + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "Destroy") std::vector<uint8_t> bytes_converted = jni_zero::ConvertArray<std::vector<uint8_t>>::FromJniType( env, - jni_zero::JavaParamRef<jbyteArray>(env, bytes)); - native->Destroy( + jni_zero::JavaParamRef<jbyteArray>(env, static_cast<jbyteArray>(bytes))); + _native->Destroy( env, jni_zero::JavaParamRef<jobject>(env, caller), bytes_converted); @@ -82,31 +82,31 @@ // Forward declaration. To be implemented by the including .cc file. static jni_zero::ScopedJavaLocalRef<jclass> JNI_SampleForTests_GetClass( JNIEnv* env, - const jni_zero::JavaParamRef<jclass>& arg0); + const jni_zero::JavaParamRef<jclass>& _env); JNI_BOUNDARY_EXPORT jclass Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getClass( JNIEnv* env, jclass jcaller, - jclass arg0) { - auto ret = JNI_SampleForTests_GetClass( + jclass _env) { + auto _ret = JNI_SampleForTests_GetClass( env, - jni_zero::JavaParamRef<jclass>(env, arg0)); - return ret.Release(); + jni_zero::JavaParamRef<jclass>(env, _env)); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static jdouble JNI_SampleForTests_GetDoubleFunction( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller); + const jni_zero::JavaParamRef<jobject>& ret); JNI_BOUNDARY_EXPORT jdouble Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getDoubleFunction( JNIEnv* env, jclass jcaller, - jobject caller) { - auto ret = JNI_SampleForTests_GetDoubleFunction( + jobject ret) { + auto _ret = JNI_SampleForTests_GetDoubleFunction( env, - jni_zero::JavaParamRef<jobject>(env, caller)); - return ret; + jni_zero::JavaParamRef<jobject>(env, ret)); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -115,8 +115,8 @@ JNI_BOUNDARY_EXPORT jfloat Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getFloatFunction( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForTests_GetFloatFunction(env); - return ret; + auto _ret = JNI_SampleForTests_GetFloatFunction(env); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -128,25 +128,25 @@ JNIEnv* env, jclass jcaller, jobject arg0) { - auto ret = JNI_SampleForTests_GetMap( + auto _ret = JNI_SampleForTests_GetMap( env, jni_zero::JavaParamRef<jobject>(env, arg0)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static jni_zero::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller); + const jni_zero::JavaParamRef<jobject>& _jcaller); JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1getNonPODDatatype( JNIEnv* env, jclass jcaller, - jobject caller) { - auto ret = JNI_SampleForTests_GetNonPODDatatype( + jobject _jcaller) { + auto _ret = JNI_SampleForTests_GetNonPODDatatype( env, - jni_zero::JavaParamRef<jobject>(env, caller)); - return ret.Release(); + jni_zero::JavaParamRef<jobject>(env, _jcaller)); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -158,10 +158,10 @@ JNIEnv* env, jclass jcaller, jthrowable arg0) { - auto ret = JNI_SampleForTests_GetThrowable( + auto _ret = JNI_SampleForTests_GetThrowable( env, jni_zero::JavaParamRef<jthrowable>(env, arg0)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -170,7 +170,8 @@ const jni_zero::JavaParamRef<jobject>& caller, const jni_zero::JavaParamRef<jstring>& param, jni_zero::ByteArrayView& bytes, - jni_zero::tests::CPPClass* convertedType); + jni_zero::tests::CPPClass* convertedType, + std::vector<jni_zero::ScopedJavaLocalRef<jobject>>& nonConvertedArray); JNI_BOUNDARY_EXPORT jlong Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1init( JNIEnv* env, @@ -178,20 +179,25 @@ jobject caller, jstring param, jbyteArray bytes, - jobject convertedType) { + jobject convertedType, + jobjectArray nonConvertedArray) { jni_zero::ByteArrayView bytes_converted = jni_zero::ConvertArray<jni_zero::ByteArrayView>::FromJniType( env, - jni_zero::JavaParamRef<jbyteArray>(env, bytes)); - jni_zero::tests::CPPClass* convertedType_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass*, jobject>( + jni_zero::JavaParamRef<jbyteArray>(env, static_cast<jbyteArray>(bytes))); + jni_zero::tests::CPPClass* convertedType_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass*>( env, jni_zero::JavaParamRef<jobject>(env, convertedType)); - auto ret = JNI_SampleForTests_Init( + std::vector<jni_zero::ScopedJavaLocalRef<jobject>> nonConvertedArray_converted = jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::FromJniType( + env, + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(nonConvertedArray))); + auto _ret = JNI_SampleForTests_Init( env, jni_zero::JavaParamRef<jobject>(env, caller), jni_zero::JavaParamRef<jstring>(env, param), bytes_converted, - convertedType_converted); - return ret; + convertedType_converted, + nonConvertedArray_converted); + return _ret; } JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1iterateAndDoSomethingWithStructB( @@ -199,9 +205,9 @@ jclass jcaller, jlong nativeCPPClass, jobject caller) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB") - native->IterateAndDoSomethingWithStructB( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "IterateAndDoSomethingWithStructB") + _native->IterateAndDoSomethingWithStructB( env, jni_zero::JavaParamRef<jobject>(env, caller)); } @@ -212,16 +218,16 @@ jlong nativeCPPClass, jobject caller, jobjectArray strings) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0) - std::vector<std::string> strings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType<jstring>( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "Method", 0) + std::vector<std::string> strings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, strings)); - auto ret = native->Method( + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(strings))); + auto _ret = _native->Method( env, jni_zero::JavaParamRef<jobject>(env, caller), strings_converted); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jdouble Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1methodOtherP0( @@ -229,12 +235,12 @@ jclass jcaller, jlong nativePtr, jobject caller) { - CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); - CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0) - auto ret = native->MethodOtherP0( + CPPClass::InnerClass* _native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); + CHECK_NATIVE_PTR(env, jcaller, _native, "MethodOtherP0", 0) + auto _ret = _native->MethodOtherP0( env, jni_zero::JavaParamRef<jobject>(env, caller)); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1returnAString( @@ -242,28 +248,28 @@ jclass jcaller, jlong nativeCPPClass, jobject caller) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", nullptr) - auto ret = native->ReturnAString( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "ReturnAString", nullptr) + auto _ret = _native->ReturnAString( env, jni_zero::JavaParamRef<jobject>(env, caller)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static void JNI_SampleForTests_SetNonPODDatatype( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller, + const jni_zero::JavaParamRef<jobject>& obj, const jni_zero::JavaParamRef<jobject>& rect); JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForTests_1setNonPODDatatype( JNIEnv* env, jclass jcaller, - jobject caller, + jobject obj, jobject rect) { JNI_SampleForTests_SetNonPODDatatype( env, - jni_zero::JavaParamRef<jobject>(env, caller), + jni_zero::JavaParamRef<jobject>(env, obj), jni_zero::JavaParamRef<jobject>(env, rect)); } @@ -282,12 +288,12 @@ "<init>", "(II)V", &cached_method_id); - auto ret = env->NewObject( + auto _ret = env->NewObject( clazz, call_context.method_id(), as_jint(foo), as_jint(bar)); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static void Java_SampleForTests_addStructA( @@ -321,12 +327,12 @@ "getClass", "(Ljava/lang/Class;)Ljava/lang/Class;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), arg0.obj()); - jclass ret2 = static_cast<jclass>(ret); - return jni_zero::ScopedJavaLocalRef<jclass>(env, ret2); + jclass _ret2 = static_cast<jclass>(_ret); + return jni_zero::ScopedJavaLocalRef<jclass>(env, _ret2); } static std::string Java_SampleForTests_getFirstString( @@ -344,22 +350,21 @@ "getFirstString", "([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", &cached_method_id); - jni_zero::ScopedJavaLocalRef<jobjectArray> array_converted = jni_zero::ConvertArray<std::vector<const char*>>::ToJniType<jstring>( + jni_zero::ScopedJavaLocalRef<jobject> converted_array = jni_zero::ConvertArray<std::vector<const char*>>::ToJniType( env, array, jni_zero::g_string_class); - jni_zero::ScopedJavaLocalRef<jstring> finalArg_converted = jni_zero::ToJniType<const char*, jstring>( + jni_zero::ScopedJavaLocalRef<jobject> converted_finalArg = jni_zero::ToJniType<const char*>( env, finalArg); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), - array_converted.obj(), - finalArg_converted.obj()); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::FromJniType<std::string, jstring>( + converted_array.obj(), + converted_finalArg.obj()); + return jni_zero::FromJniType<std::string>( env, - jni_zero::JavaParamRef<jstring>(env, ret2)); + jni_zero::JavaParamRef<jobject>(env, _ret)); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum( @@ -374,8 +379,8 @@ "getInnerEnum", "()Lorg/jni_zero/SampleForTests$InnerEnum;", &cached_method_id); - auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum( @@ -391,11 +396,11 @@ "getInnerEnum", "(I)Lorg/jni_zero/SampleForTests$InnerEnum;", &cached_method_id); - auto ret = env->CallStaticObjectMethod( + auto _ret = env->CallStaticObjectMethod( clazz, call_context.method_id(), as_jint(a)); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerInterface( @@ -410,8 +415,8 @@ "getInnerInterface", "()Lorg/jni_zero/SampleForTests$InnerInterface;", &cached_method_id); - auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jthrowable> Java_SampleForTests_getThrowable( @@ -428,12 +433,12 @@ "getThrowable", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), arg0.obj()); - jthrowable ret2 = static_cast<jthrowable>(ret); - return jni_zero::ScopedJavaLocalRef<jthrowable>(env, ret2); + jthrowable _ret2 = static_cast<jthrowable>(_ret); + return jni_zero::ScopedJavaLocalRef<jthrowable>(env, _ret2); } static void Java_SampleForTests_iterateAndDoSomething( @@ -455,8 +460,8 @@ static jint Java_SampleForTests_javaMethod( JNIEnv* env, const jni_zero::JavaRef<jobject>& obj, - JniIntWrapper foo, - JniIntWrapper bar) { + JniIntWrapper _jcaller, + JniIntWrapper ret) { static std::atomic<jmethodID> cached_method_id(nullptr); jclass clazz = org_jni_1zero_SampleForTests_clazz(env); CHECK_CLAZZ(env, obj.obj(), clazz, 0); @@ -467,12 +472,12 @@ "javaMethod", "(II)I", &cached_method_id); - auto ret = env->CallIntMethod( + auto _ret = env->CallIntMethod( obj.obj(), call_context.method_id(), - as_jint(foo), - as_jint(bar)); - return ret; + as_jint(_jcaller), + as_jint(ret)); + return _ret; } static void Java_SampleForTests_javaMethodWithAnnotatedParam( @@ -492,15 +497,15 @@ "javaMethodWithAnnotatedParam", "(IIIJ)V", &cached_method_id); - jint foo_converted = static_cast<jint>(foo); - jlong bat_converted = static_cast<jlong>(bat); + jint converted_foo = static_cast<jint>(foo); + jlong converted_bat = static_cast<jlong>(bat); env->CallVoidMethod( obj.obj(), call_context.method_id(), - foo_converted, + converted_foo, as_jint(bar), as_jint(baz), - bat_converted); + converted_bat); } static void Java_SampleForTests_methodThatThrowsException( @@ -532,14 +537,14 @@ "methodWithAnnotationParamAssignment", "()Z", &cached_method_id); - auto ret = env->CallBooleanMethod(obj.obj(), call_context.method_id()); - return ret; + auto _ret = env->CallBooleanMethod(obj.obj(), call_context.method_id()); + return _ret; } static void Java_SampleForTests_methodWithGenericParams( JNIEnv* env, const jni_zero::JavaRef<jobject>& obj, - const jni_zero::JavaRef<jobject>& foo, + const jni_zero::JavaRef<jobject>& _env, const jni_zero::JavaRef<jobject>& bar) { static std::atomic<jmethodID> cached_method_id(nullptr); jclass clazz = org_jni_1zero_SampleForTests_clazz(env); @@ -554,7 +559,7 @@ env->CallVoidMethod( obj.obj(), call_context.method_id(), - foo.obj(), + _env.obj(), bar.obj()); } @@ -585,8 +590,8 @@ "staticJavaMethod", "()Z", &cached_method_id); - auto ret = env->CallStaticBooleanMethod(clazz, call_context.method_id()); - return ret; + auto _ret = env->CallStaticBooleanMethod(clazz, call_context.method_id()); + return _ret; } static jni_zero::ScopedJavaLocalRef<jobject> Java_InnerStructA_create( @@ -604,13 +609,13 @@ "create", "(JILjava/lang/String;)Lorg/jni_zero/SampleForTests$InnerStructA;", &cached_method_id); - auto ret = env->CallStaticObjectMethod( + auto _ret = env->CallStaticObjectMethod( clazz, call_context.method_id(), l, as_jint(i), s.obj()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jlong Java_InnerStructB_getKey( @@ -626,8 +631,8 @@ "getKey", "()J", &cached_method_id); - auto ret = env->CallLongMethod(obj.obj(), call_context.method_id()); - return ret; + auto _ret = env->CallLongMethod(obj.obj(), call_context.method_id()); + return _ret; } static jni_zero::ScopedJavaLocalRef<jstring> Java_InnerStructB_getValue( @@ -643,9 +648,9 @@ "getValue", "()Ljava/lang/String;", &cached_method_id); - auto ret = env->CallObjectMethod(obj.obj(), call_context.method_id()); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::ScopedJavaLocalRef<jstring>(env, ret2); + auto _ret = env->CallObjectMethod(obj.obj(), call_context.method_id()); + jstring _ret2 = static_cast<jstring>(_ret); + return jni_zero::ScopedJavaLocalRef<jstring>(env, _ret2); }
diff --git a/third_party/jni_zero/test/golden/testBirectionalNonProxy-SampleBidirectionalNonProxy_jni.h.golden b/third_party/jni_zero/test/golden/testBirectionalNonProxy-SampleBidirectionalNonProxy_jni.h.golden index 0d861ac..524361f 100644 --- a/third_party/jni_zero/test/golden/testBirectionalNonProxy-SampleBidirectionalNonProxy_jni.h.golden +++ b/third_party/jni_zero/test/golden/testBirectionalNonProxy-SampleBidirectionalNonProxy_jni.h.golden
@@ -29,10 +29,10 @@ JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleBidirectionalNonProxy_nativeInit( JNIEnv* env, jobject jcaller) { - auto ret = JNI_SampleBidirectionalNonProxy_Init( + auto _ret = JNI_SampleBidirectionalNonProxy_Init( env, jni_zero::JavaParamRef<jobject>(env, jcaller)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -43,10 +43,10 @@ JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleBidirectionalNonProxy_nativeInit( JNIEnv* env, jobject jcaller) { - auto ret = JNI_SampleBidirectionalNonProxy_Init( + auto _ret = JNI_SampleBidirectionalNonProxy_Init( env, jni_zero::JavaParamRef<jobject>(env, jcaller)); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleBidirectionalNonProxy_nativeMethod( @@ -54,13 +54,13 @@ jobject jcaller, jlong nativeTest, jint arg1) { - Test* native = reinterpret_cast<Test*>(nativeTest); - CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0) - auto ret = native->Method( + Test* _native = reinterpret_cast<Test*>(nativeTest); + CHECK_NATIVE_PTR(env, jcaller, _native, "Method", 0) + auto _ret = _native->Method( env, jni_zero::JavaParamRef<jobject>(env, jcaller), arg1); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleBidirectionalNonProxy_nativeStaticMethod( @@ -68,10 +68,10 @@ jclass jcaller, jlong nativeTest, jint arg1) { - Test* native = reinterpret_cast<Test*>(nativeTest); - CHECK_NATIVE_PTR(env, jcaller, native, "StaticMethod", 0) - auto ret = native->StaticMethod(env, arg1); - return ret; + Test* _native = reinterpret_cast<Test*>(nativeTest); + CHECK_NATIVE_PTR(env, jcaller, _native, "StaticMethod", 0) + auto _ret = _native->StaticMethod(env, arg1); + return _ret; } // Native to Java functions @@ -144,8 +144,8 @@ "testMethodWithNoParam", "()D", &cached_method_id); - auto ret = env->CallStaticDoubleMethod(clazz, call_context.method_id()); - return ret; + auto _ret = env->CallStaticDoubleMethod(clazz, call_context.method_id()); + return _ret; } static void Java_SampleBidirectionalNonProxy_testMethodWithParam( @@ -179,12 +179,12 @@ "testMethodWithParamAndReturn", "(I)Ljava/lang/String;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), as_jint(iParam)); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::ScopedJavaLocalRef<jstring>(env, ret2); + jstring _ret2 = static_cast<jstring>(_ret); + return jni_zero::ScopedJavaLocalRef<jstring>(env, _ret2); } static jni_zero::ScopedJavaLocalRef<jstring> Java_SampleBidirectionalNonProxy_testStaticMethodWithNoParam( @@ -199,9 +199,9 @@ "testStaticMethodWithNoParam", "()Ljava/lang/String;", &cached_method_id); - auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::ScopedJavaLocalRef<jstring>(env, ret2); + auto _ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); + jstring _ret2 = static_cast<jstring>(_ret); + return jni_zero::ScopedJavaLocalRef<jstring>(env, _ret2); } static jint Java_SampleBidirectionalNonProxy_testStaticMethodWithParam( @@ -217,11 +217,11 @@ "testStaticMethodWithParam", "(I)I", &cached_method_id); - auto ret = env->CallStaticIntMethod( + auto _ret = env->CallStaticIntMethod( clazz, call_context.method_id(), as_jint(iParam)); - return ret; + return _ret; }
diff --git a/third_party/jni_zero/test/golden/testEndToEndProxyHashed-SampleForAnnotationProcessor_jni.h.golden b/third_party/jni_zero/test/golden/testEndToEndProxyHashed-SampleForAnnotationProcessor_jni.h.golden index c2e99a0..38bc1e4 100644 --- a/third_party/jni_zero/test/golden/testEndToEndProxyHashed-SampleForAnnotationProcessor_jni.h.golden +++ b/third_party/jni_zero/test/golden/testEndToEndProxyHashed-SampleForAnnotationProcessor_jni.h.golden
@@ -23,10 +23,10 @@ // Forward declare used conversion functions to avoid a compiler warning that // triggers if a conversion specialization exists within the including .cc file. namespace jni_zero { -template<> jni_zero::ScopedJavaLocalRef<jstring> ToJniType<std::string, jstring>(JNIEnv*, std::string const&); -template<> jni_zero::tests::CPPClass FromJniType<jni_zero::tests::CPPClass, jobject>(JNIEnv*, const JavaRef<jobject>&); -template<> std::optional<std::string> FromJniType<std::optional<std::string>, jstring>(JNIEnv*, const JavaRef<jstring>&); -template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&); +template<> jni_zero::ScopedJavaLocalRef<jobject> ToJniType<std::string>(JNIEnv*, std::string const&); +template<> jni_zero::tests::CPPClass FromJniType<jni_zero::tests::CPPClass>(JNIEnv*, const JavaRef<jobject>&); +template<> std::optional<std::string> FromJniType<std::optional<std::string>>(JNIEnv*, const JavaRef<jobject>&); +template<> std::string FromJniType<std::string>(JNIEnv*, const JavaRef<jobject>&); } // namespace jni_zero // Java to native functions // Forward declaration. To be implemented by the including .cc file. @@ -38,10 +38,10 @@ JNIEnv* env, jclass jcaller, jobject sample) { - auto ret = JNI_SampleForAnnotationProcessor_Bar( + auto _ret = JNI_SampleForAnnotationProcessor_Bar( env, jni_zero::JavaParamRef<jobject>(env, sample)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -59,8 +59,8 @@ JNI_BOUNDARY_EXPORT jboolean Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1hasPhalange( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_HasPhalange(env); - return ret; + auto _ret = JNI_SampleForAnnotationProcessor_HasPhalange(env); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -70,8 +70,8 @@ JNI_BOUNDARY_EXPORT jclass Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnClass( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnClass(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnClass(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -81,8 +81,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnClasses( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnClasses(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnClasses(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -93,11 +93,12 @@ JNIEnv* env, jclass jcaller, jclass __arrayClazz) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedAppObjects(env); - return jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::ToJniType<jobject>( + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedAppObjects(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::ToJniType( env, - ret, + _ret, __arrayClazz).Release(); + return static_cast<jobjectArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -107,8 +108,11 @@ JNI_BOUNDARY_EXPORT jintArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnConvertedInts( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedInts(env); - return jni_zero::ConvertArray<std::vector<jint>>::ToJniType(env, ret).Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedInts(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<jint>>::ToJniType( + env, + _ret).Release(); + return static_cast<jintArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -118,8 +122,9 @@ JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnConvertedString( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedString(env); - return jni_zero::ToJniType<std::string, jstring>(env, ret).Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedString(env); + jobject converted_ret = jni_zero::ToJniType<std::string>(env, _ret).Release(); + return static_cast<jstring>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -129,11 +134,12 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnConvertedStrings( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedStrings(env); - return jni_zero::ConvertArray<std::vector<std::string>>::ToJniType<jstring>( + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedStrings(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<std::string>>::ToJniType( env, - ret, + _ret, jni_zero::g_string_class).Release(); + return static_cast<jobjectArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -143,8 +149,8 @@ JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnObject( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnObject(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnObject(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -154,8 +160,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnObjects( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnObjects(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnObjects(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -165,8 +171,8 @@ JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnString( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnString(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnString(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -176,8 +182,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnStrings( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStrings(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStrings(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -187,8 +193,8 @@ JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnStruct( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStruct(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStruct(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -198,8 +204,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnStructs( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStructs(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStructs(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -209,8 +215,8 @@ JNI_BOUNDARY_EXPORT jthrowable Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnThrowable( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnThrowable(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnThrowable(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -220,8 +226,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleForAnnotationProcessor_1returnThrowables( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnThrowables(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnThrowables(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -233,10 +239,10 @@ JNIEnv* env, jclass jcaller, jstring stringToReverse) { - auto ret = JNI_SampleForAnnotationProcessor_RevString( + auto _ret = JNI_SampleForAnnotationProcessor_RevString( env, jni_zero::JavaParamRef<jstring>(env, stringToReverse)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -248,10 +254,10 @@ JNIEnv* env, jclass jcaller, jobjectArray strs) { - auto ret = JNI_SampleForAnnotationProcessor_SendSamplesToNative( + auto _ret = JNI_SampleForAnnotationProcessor_SendSamplesToNative( env, jni_zero::JavaParamRef<jobjectArray>(env, strs)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -263,10 +269,10 @@ JNIEnv* env, jclass jcaller, jobjectArray strs) { - auto ret = JNI_SampleForAnnotationProcessor_SendToNative( + auto _ret = JNI_SampleForAnnotationProcessor_SendToNative( env, jni_zero::JavaParamRef<jobjectArray>(env, strs)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -311,9 +317,9 @@ int zint_converted = static_cast<int>(zint); std::vector<int32_t> ints_converted = jni_zero::ConvertArray<std::vector<int32_t>>::FromJniType( env, - jni_zero::JavaParamRef<jintArray>(env, ints)); + jni_zero::JavaParamRef<jintArray>(env, static_cast<jintArray>(ints))); int zchar_converted = static_cast<int>(zchar); - auto ret = JNI_SampleForAnnotationProcessor_TestAllPrimitives( + auto _ret = JNI_SampleForAnnotationProcessor_TestAllPrimitives( env, zint_converted, ints_converted, @@ -331,7 +337,10 @@ jni_zero::JavaParamRef<jfloatArray>(env, floats), zbool, jni_zero::JavaParamRef<jbooleanArray>(env, bools)); - return jni_zero::ConvertArray<std::vector<int32_t>>::ToJniType(env, ret).Release(); + jobject converted_ret = jni_zero::ConvertArray<std::vector<int32_t>>::ToJniType( + env, + _ret).Release(); + return static_cast<jintArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -377,21 +386,21 @@ jobject view, jobject context, jobjectArray convertedObjects) { - std::string convertedString_converted = jni_zero::FromJniType<std::string, jstring>( + std::string convertedString_converted = jni_zero::FromJniType<std::string>( env, - jni_zero::JavaParamRef<jstring>(env, convertedString)); - std::vector<std::string> convertedStrings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType<jstring>( + jni_zero::JavaParamRef<jobject>(env, convertedString)); + std::vector<std::string> convertedStrings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, convertedStrings)); - std::optional<std::string> optionalString_converted = jni_zero::FromJniType<std::optional<std::string>, jstring>( + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(convertedStrings))); + std::optional<std::string> optionalString_converted = jni_zero::FromJniType<std::optional<std::string>>( env, - jni_zero::JavaParamRef<jstring>(env, optionalString)); - jni_zero::tests::CPPClass convertedObj_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass, jobject>( + jni_zero::JavaParamRef<jobject>(env, optionalString)); + jni_zero::tests::CPPClass convertedObj_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass>( env, jni_zero::JavaParamRef<jobject>(env, convertedObj)); - std::vector<jni_zero::tests::CPPClass> convertedObjects_converted = jni_zero::ConvertArray<std::vector<jni_zero::tests::CPPClass>>::FromJniType<jobject>( + std::vector<jni_zero::tests::CPPClass> convertedObjects_converted = jni_zero::ConvertArray<std::vector<jni_zero::tests::CPPClass>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, convertedObjects)); + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(convertedObjects))); JNI_SampleForAnnotationProcessor_TestSpecialTypes( env, jni_zero::JavaParamRef<jclass>(env, clazz),
diff --git a/third_party/jni_zero/test/golden/testEndToEndProxyJniWithModules-SampleModule_jni.h.golden b/third_party/jni_zero/test/golden/testEndToEndProxyJniWithModules-SampleModule_jni.h.golden index 9bd04f981..77038192 100644 --- a/third_party/jni_zero/test/golden/testEndToEndProxyJniWithModules-SampleModule_jni.h.golden +++ b/third_party/jni_zero/test/golden/testEndToEndProxyJniWithModules-SampleModule_jni.h.golden
@@ -18,8 +18,8 @@ JNIEnv* env, jclass jcaller, jint a) { - auto ret = JNI_SampleModule_Bar(env, a); - return ret; + auto _ret = JNI_SampleModule_Bar(env, a); + return _ret; } // Forward declaration. To be implemented by the including .cc file.
diff --git a/third_party/jni_zero/test/golden/testForTestingKept-SampleProxyEdgeCases_jni.h.golden b/third_party/jni_zero/test/golden/testForTestingKept-SampleProxyEdgeCases_jni.h.golden index 7ebe391..6fdfd73 100644 --- a/third_party/jni_zero/test/golden/testForTestingKept-SampleProxyEdgeCases_jni.h.golden +++ b/third_party/jni_zero/test/golden/testForTestingKept-SampleProxyEdgeCases_jni.h.golden
@@ -22,11 +22,11 @@ jclass jcaller, jobject caller, jobject b) { - auto ret = JNI_SampleProxyEdgeCases_AddStructB( + auto _ret = JNI_SampleProxyEdgeCases_AddStructB( env, jni_zero::JavaParamRef<jobject>(env, caller), jni_zero::JavaParamRef<jobject>(env, b)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -40,11 +40,11 @@ jclass jcaller, jintArray a, jobjectArray b) { - auto ret = JNI_SampleProxyEdgeCases_ArrayTypes1( + auto _ret = JNI_SampleProxyEdgeCases_ArrayTypes1( env, jni_zero::JavaParamRef<jintArray>(env, a), jni_zero::JavaParamRef<jobjectArray>(env, b)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -58,11 +58,11 @@ jclass jcaller, jintArray a, jobjectArray b) { - auto ret = JNI_SampleProxyEdgeCases_ArrayTypes2( + auto _ret = JNI_SampleProxyEdgeCases_ArrayTypes2( env, jni_zero::JavaParamRef<jintArray>(env, a), jni_zero::JavaParamRef<jobjectArray>(env, b)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -110,10 +110,10 @@ JNIEnv* env, jclass jcaller, jobjectArray arg) { - auto ret = JNI_SampleProxyEdgeCases_GenericsWithNestedClassArray( + auto _ret = JNI_SampleProxyEdgeCases_GenericsWithNestedClassArray( env, jni_zero::JavaParamRef<jobjectArray>(env, arg)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -142,10 +142,10 @@ JNIEnv* env, jclass jcaller, jobject sb) { - auto ret = JNI_SampleProxyEdgeCases_SetStringBuilder( + auto _ret = JNI_SampleProxyEdgeCases_SetStringBuilder( env, jni_zero::JavaParamRef<jobject>(env, sb)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -155,17 +155,17 @@ JNIEnv* env, jclass jcaller, jint sb) { - auto ret = JNI_SampleProxyEdgeCases_SetStringBuilder(env, sb); - return ret; + auto _ret = JNI_SampleProxyEdgeCases_SetStringBuilder(env, sb); + return _ret; } JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_SampleProxyEdgeCases_nativeInstanceMethod( JNIEnv* env, jobject jcaller, jlong nativeInstance) { - Instance* native = reinterpret_cast<Instance*>(nativeInstance); - CHECK_NATIVE_PTR(env, jcaller, native, "InstanceMethod") - native->InstanceMethod(env, jni_zero::JavaParamRef<jobject>(env, jcaller)); + Instance* _native = reinterpret_cast<Instance*>(nativeInstance); + CHECK_NATIVE_PTR(env, jcaller, _native, "InstanceMethod") + _native->InstanceMethod(env, jni_zero::JavaParamRef<jobject>(env, jcaller)); } // Forward declaration. To be implemented by the including .cc file.
diff --git a/third_party/jni_zero/test/golden/testFromClassFile-JavapClass_jni.h.golden b/third_party/jni_zero/test/golden/testFromClassFile-JavapClass_jni.h.golden index 9e4c00fb..a76b27f0 100644 --- a/third_party/jni_zero/test/golden/testFromClassFile-JavapClass_jni.h.golden +++ b/third_party/jni_zero/test/golden/testFromClassFile-JavapClass_jni.h.golden
@@ -39,8 +39,8 @@ "<init>", "()V", &cached_method_id); - auto ret = env->NewObject(clazz, call_context.method_id()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->NewObject(clazz, call_context.method_id()); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } [[maybe_unused]] static jni_zero::ScopedJavaLocalRef<jobject> Java_JavapClass_Constructor__boolean( @@ -56,8 +56,8 @@ "<init>", "(Z)V", &cached_method_id); - auto ret = env->NewObject(clazz, call_context.method_id(), p0); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->NewObject(clazz, call_context.method_id(), p0); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } [[maybe_unused]] static jni_zero::ScopedJavaLocalRef<jobject> Java_JavapClass_Constructor__int( @@ -73,8 +73,8 @@ "<init>", "(I)V", &cached_method_id); - auto ret = env->NewObject(clazz, call_context.method_id(), as_jint(p0)); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->NewObject(clazz, call_context.method_id(), as_jint(p0)); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } [[maybe_unused]] static jint Java_JavapClass_intMethod( @@ -91,8 +91,11 @@ "intMethod", "(Ljava/lang/String;)I", &cached_method_id); - auto ret = env->CallIntMethod(obj.obj(), call_context.method_id(), p0.obj()); - return ret; + auto _ret = env->CallIntMethod( + obj.obj(), + call_context.method_id(), + p0.obj()); + return _ret; } [[maybe_unused]] static void Java_JavapClass_needsMangling__String( @@ -158,13 +161,13 @@ "objTest", "(Ljava/lang/Object;[Ljava/lang/Runnable;)Ljava/lang/Class;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), p0.obj(), p1.obj()); - jclass ret2 = static_cast<jclass>(ret); - return jni_zero::ScopedJavaLocalRef<jclass>(env, ret2); + jclass _ret2 = static_cast<jclass>(_ret); + return jni_zero::ScopedJavaLocalRef<jclass>(env, _ret2); } [[maybe_unused]] static jint Java_JavapClass_staticIntMethod( @@ -181,12 +184,12 @@ "staticIntMethod", "(Ljava/lang/String;Lorg/jni_zero/JavapClass;)I", &cached_method_id); - auto ret = env->CallStaticIntMethod( + auto _ret = env->CallStaticIntMethod( clazz, call_context.method_id(), p0.obj(), p1.obj()); - return ret; + return _ret; } [[maybe_unused]] static jni_zero::ScopedJavaLocalRef<jobjectArray> Java_JavapClass_staticIntMethod( @@ -202,12 +205,12 @@ "staticIntMethod", "(Ljava/lang/String;)[[I", &cached_method_id); - auto ret = env->CallStaticObjectMethod( + auto _ret = env->CallStaticObjectMethod( clazz, call_context.method_id(), p0.obj()); - jobjectArray ret2 = static_cast<jobjectArray>(ret); - return jni_zero::ScopedJavaLocalRef<jobjectArray>(env, ret2); + jobjectArray _ret2 = static_cast<jobjectArray>(_ret); + return jni_zero::ScopedJavaLocalRef<jobjectArray>(env, _ret2); }
diff --git a/third_party/jni_zero/test/golden/testNonProxy-SampleNonProxy_jni.h.golden b/third_party/jni_zero/test/golden/testNonProxy-SampleNonProxy_jni.h.golden index d92d7ab9..e0d1df5 100644 --- a/third_party/jni_zero/test/golden/testNonProxy-SampleNonProxy_jni.h.golden +++ b/third_party/jni_zero/test/golden/testNonProxy-SampleNonProxy_jni.h.golden
@@ -29,7 +29,7 @@ jstring title, jboolean isFolder, jlong parentId) { - auto ret = JNI_SampleNonProxy_AddBookmark( + auto _ret = JNI_SampleNonProxy_AddBookmark( env, jni_zero::JavaParamRef<jobject>(env, jcaller), nativeChromeBrowserProvider, @@ -37,7 +37,7 @@ jni_zero::JavaParamRef<jstring>(env, title), isFolder, parentId); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -64,7 +64,7 @@ jbyteArray favicon, jstring title, jobject visits) { - auto ret = JNI_SampleNonProxy_AddBookmarkFromAPI( + auto _ret = JNI_SampleNonProxy_AddBookmarkFromAPI( env, jni_zero::JavaParamRef<jobject>(env, jcaller), nativeChromeBrowserProvider, @@ -75,7 +75,7 @@ jni_zero::JavaParamRef<jbyteArray>(env, favicon), jni_zero::JavaParamRef<jstring>(env, title), jni_zero::JavaParamRef<jobject>(env, visits)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -121,11 +121,11 @@ JNIEnv* env, jobject jcaller, jstring find) { - auto ret = JNI_SampleNonProxy_FindAll( + auto _ret = JNI_SampleNonProxy_FindAll( env, jni_zero::JavaParamRef<jobject>(env, jcaller), jni_zero::JavaParamRef<jstring>(env, find)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -135,8 +135,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleNonProxy_nativeGetAutofillProfileGUIDs( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleNonProxy_GetAutofillProfileGUIDs(env); - return ret.Release(); + auto _ret = JNI_SampleNonProxy_GetAutofillProfileGUIDs(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -148,10 +148,10 @@ JNIEnv* env, jclass jcaller, jstring url) { - auto ret = JNI_SampleNonProxy_GetDomainAndRegistry( + auto _ret = JNI_SampleNonProxy_GetDomainAndRegistry( env, jni_zero::JavaParamRef<jstring>(env, url)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -161,8 +161,8 @@ JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_SampleNonProxy_nativeGetInnerClass( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleNonProxy_GetInnerClass(env); - return ret.Release(); + auto _ret = JNI_SampleNonProxy_GetInnerClass(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -175,11 +175,11 @@ JNIEnv* env, jobject jcaller, jobject view) { - auto ret = JNI_SampleNonProxy_GetStateAsByteArray( + auto _ret = JNI_SampleNonProxy_GetStateAsByteArray( env, jni_zero::JavaParamRef<jobject>(env, jcaller), jni_zero::JavaParamRef<jobject>(env, view)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -215,10 +215,10 @@ JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleNonProxy_nativeInit( JNIEnv* env, jobject jcaller) { - auto ret = JNI_SampleNonProxy_Init( + auto _ret = JNI_SampleNonProxy_Init( env, jni_zero::JavaParamRef<jobject>(env, jcaller)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -229,10 +229,10 @@ JNI_BOUNDARY_EXPORT jint Java_org_jni_1zero_SampleNonProxy_nativeInit( JNIEnv* env, jobject jcaller) { - auto ret = JNI_SampleNonProxy_Init( + auto _ret = JNI_SampleNonProxy_Init( env, jni_zero::JavaParamRef<jobject>(env, jcaller)); - return ret; + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -244,10 +244,10 @@ JNIEnv* env, jclass jcaller, jthrowable e) { - auto ret = JNI_SampleNonProxy_MessWithJavaException( + auto _ret = JNI_SampleNonProxy_MessWithJavaException( env, jni_zero::JavaParamRef<jthrowable>(env, e)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -268,7 +268,7 @@ jstring selection, jobjectArray selectionArgs, jstring sortOrder) { - auto ret = JNI_SampleNonProxy_QueryBitmap( + auto _ret = JNI_SampleNonProxy_QueryBitmap( env, jni_zero::JavaParamRef<jobject>(env, jcaller), nativeChromeBrowserProvider, @@ -276,7 +276,7 @@ jni_zero::JavaParamRef<jstring>(env, selection), jni_zero::JavaParamRef<jobjectArray>(env, selectionArgs), jni_zero::JavaParamRef<jstring>(env, sortOrder)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file.
diff --git a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-Placeholder-GEN_JNI.java.golden b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-Placeholder-GEN_JNI.java.golden index 598f2b7f..f2f0f3b 100644 --- a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-Placeholder-GEN_JNI.java.golden +++ b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-Placeholder-GEN_JNI.java.golden
@@ -10,16 +10,16 @@ public static native void this_is_a_package_prefix_org_jni_1zero_SampleForTests_addStructB(long nativeCPPClass, Object caller, Object b); public static native void this_is_a_package_prefix_org_jni_1zero_SampleForTests_destroy(long nativeCPPClass, Object caller, byte[] bytes); - public static native Class this_is_a_package_prefix_org_jni_1zero_SampleForTests_getClass(Class arg0); - public static native double this_is_a_package_prefix_org_jni_1zero_SampleForTests_getDoubleFunction(Object caller); + public static native Class this_is_a_package_prefix_org_jni_1zero_SampleForTests_getClass(Class env); + public static native double this_is_a_package_prefix_org_jni_1zero_SampleForTests_getDoubleFunction(Object ret); public static native float this_is_a_package_prefix_org_jni_1zero_SampleForTests_getFloatFunction(); public static native Object this_is_a_package_prefix_org_jni_1zero_SampleForTests_getMap(Object arg0); - public static native Object this_is_a_package_prefix_org_jni_1zero_SampleForTests_getNonPODDatatype(Object caller); + public static native Object this_is_a_package_prefix_org_jni_1zero_SampleForTests_getNonPODDatatype(Object jcaller); public static native Throwable this_is_a_package_prefix_org_jni_1zero_SampleForTests_getThrowable(Throwable arg0); - public static native long this_is_a_package_prefix_org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType); + public static native long this_is_a_package_prefix_org_jni_1zero_SampleForTests_init(Object caller, String param, byte[] bytes, Object convertedType, Object[] nonConvertedArray); public static native void this_is_a_package_prefix_org_jni_1zero_SampleForTests_iterateAndDoSomethingWithStructB(long nativeCPPClass, Object caller); public static native int this_is_a_package_prefix_org_jni_1zero_SampleForTests_method(long nativeCPPClass, Object caller, String[] strings); public static native double this_is_a_package_prefix_org_jni_1zero_SampleForTests_methodOtherP0(long nativePtr, Object caller); public static native String this_is_a_package_prefix_org_jni_1zero_SampleForTests_returnAString(long nativeCPPClass, Object caller); - public static native void this_is_a_package_prefix_org_jni_1zero_SampleForTests_setNonPODDatatype(Object caller, Object rect); + public static native void this_is_a_package_prefix_org_jni_1zero_SampleForTests_setNonPODDatatype(Object obj, Object rect); }
diff --git a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTestsJni.java.golden b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTestsJni.java.golden index a80a4bf..f6489c4 100644 --- a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTestsJni.java.golden +++ b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTestsJni.java.golden
@@ -40,13 +40,13 @@ } @Override - public Class getClass(Class arg0) { - return (Class) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getClass(arg0); + public Class getClass(Class env) { + return (Class) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getClass(env); } @Override - public double getDoubleFunction(SampleForTests caller) { - return (double) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getDoubleFunction(caller); + public double getDoubleFunction(SampleForTests ret) { + return (double) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getDoubleFunction(ret); } @Override @@ -60,8 +60,8 @@ } @Override - public Object getNonPODDatatype(SampleForTests caller) { - return (Object) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getNonPODDatatype(caller); + public Object getNonPODDatatype(SampleForTests jcaller) { + return (Object) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_getNonPODDatatype(jcaller); } @Override @@ -70,8 +70,8 @@ } @Override - public long init(SampleForTests caller, String param, byte[] bytes, SampleForTests convertedType) { - return (long) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_init(caller, param, bytes, convertedType); + public long init(SampleForTests caller, String param, byte[] bytes, SampleForTests convertedType, SampleForTests[] nonConvertedArray) { + return (long) GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_init(caller, param, bytes, convertedType, nonConvertedArray); } @Override @@ -99,8 +99,8 @@ } @Override - public void setNonPODDatatype(SampleForTests caller, Rect rect) { - GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_setNonPODDatatype(caller, rect); + public void setNonPODDatatype(SampleForTests obj, Rect rect) { + GEN_JNI.this_is_a_package_prefix_org_jni_1zero_SampleForTests_setNonPODDatatype(obj, rect); } public static SampleForTests.Natives get() {
diff --git a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTests_jni.h.golden b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTests_jni.h.golden index 9349600..12bbc73 100644 --- a/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTests_jni.h.golden +++ b/third_party/jni_zero/test/golden/testPackagePrefixGenerator-SampleForTests_jni.h.golden
@@ -41,9 +41,9 @@ // Forward declare used conversion functions to avoid a compiler warning that // triggers if a conversion specialization exists within the including .cc file. namespace jni_zero { -template<> jni_zero::ScopedJavaLocalRef<jstring> ToJniType<const char*, jstring>(JNIEnv*, const char* const&); -template<> jni_zero::tests::CPPClass* FromJniType<jni_zero::tests::CPPClass*, jobject>(JNIEnv*, const JavaRef<jobject>&); -template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&); +template<> jni_zero::ScopedJavaLocalRef<jobject> ToJniType<const char*>(JNIEnv*, const char* const&); +template<> jni_zero::tests::CPPClass* FromJniType<jni_zero::tests::CPPClass*>(JNIEnv*, const JavaRef<jobject>&); +template<> std::string FromJniType<std::string>(JNIEnv*, const JavaRef<jobject>&); } // namespace jni_zero namespace jni_zero { namespace tests { @@ -54,9 +54,9 @@ jlong nativeCPPClass, jobject caller, jobject b) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB") - native->AddStructB( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "AddStructB") + _native->AddStructB( env, jni_zero::JavaParamRef<jobject>(env, caller), jni_zero::JavaParamRef<jobject>(env, b)); @@ -68,12 +68,12 @@ jlong nativeCPPClass, jobject caller, jbyteArray bytes) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "Destroy") + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "Destroy") std::vector<uint8_t> bytes_converted = jni_zero::ConvertArray<std::vector<uint8_t>>::FromJniType( env, - jni_zero::JavaParamRef<jbyteArray>(env, bytes)); - native->Destroy( + jni_zero::JavaParamRef<jbyteArray>(env, static_cast<jbyteArray>(bytes))); + _native->Destroy( env, jni_zero::JavaParamRef<jobject>(env, caller), bytes_converted); @@ -82,31 +82,31 @@ // Forward declaration. To be implemented by the including .cc file. static jni_zero::ScopedJavaLocalRef<jclass> JNI_SampleForTests_GetClass( JNIEnv* env, - const jni_zero::JavaParamRef<jclass>& arg0); + const jni_zero::JavaParamRef<jclass>& _env); JNI_BOUNDARY_EXPORT jclass Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1getClass( JNIEnv* env, jclass jcaller, - jclass arg0) { - auto ret = JNI_SampleForTests_GetClass( + jclass _env) { + auto _ret = JNI_SampleForTests_GetClass( env, - jni_zero::JavaParamRef<jclass>(env, arg0)); - return ret.Release(); + jni_zero::JavaParamRef<jclass>(env, _env)); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static jdouble JNI_SampleForTests_GetDoubleFunction( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller); + const jni_zero::JavaParamRef<jobject>& ret); JNI_BOUNDARY_EXPORT jdouble Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1getDoubleFunction( JNIEnv* env, jclass jcaller, - jobject caller) { - auto ret = JNI_SampleForTests_GetDoubleFunction( + jobject ret) { + auto _ret = JNI_SampleForTests_GetDoubleFunction( env, - jni_zero::JavaParamRef<jobject>(env, caller)); - return ret; + jni_zero::JavaParamRef<jobject>(env, ret)); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -115,8 +115,8 @@ JNI_BOUNDARY_EXPORT jfloat Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1getFloatFunction( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForTests_GetFloatFunction(env); - return ret; + auto _ret = JNI_SampleForTests_GetFloatFunction(env); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -128,25 +128,25 @@ JNIEnv* env, jclass jcaller, jobject arg0) { - auto ret = JNI_SampleForTests_GetMap( + auto _ret = JNI_SampleForTests_GetMap( env, jni_zero::JavaParamRef<jobject>(env, arg0)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static jni_zero::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller); + const jni_zero::JavaParamRef<jobject>& _jcaller); JNI_BOUNDARY_EXPORT jobject Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1getNonPODDatatype( JNIEnv* env, jclass jcaller, - jobject caller) { - auto ret = JNI_SampleForTests_GetNonPODDatatype( + jobject _jcaller) { + auto _ret = JNI_SampleForTests_GetNonPODDatatype( env, - jni_zero::JavaParamRef<jobject>(env, caller)); - return ret.Release(); + jni_zero::JavaParamRef<jobject>(env, _jcaller)); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -158,10 +158,10 @@ JNIEnv* env, jclass jcaller, jthrowable arg0) { - auto ret = JNI_SampleForTests_GetThrowable( + auto _ret = JNI_SampleForTests_GetThrowable( env, jni_zero::JavaParamRef<jthrowable>(env, arg0)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -170,7 +170,8 @@ const jni_zero::JavaParamRef<jobject>& caller, const jni_zero::JavaParamRef<jstring>& param, jni_zero::ByteArrayView& bytes, - jni_zero::tests::CPPClass* convertedType); + jni_zero::tests::CPPClass* convertedType, + std::vector<jni_zero::ScopedJavaLocalRef<jobject>>& nonConvertedArray); JNI_BOUNDARY_EXPORT jlong Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1init( JNIEnv* env, @@ -178,20 +179,25 @@ jobject caller, jstring param, jbyteArray bytes, - jobject convertedType) { + jobject convertedType, + jobjectArray nonConvertedArray) { jni_zero::ByteArrayView bytes_converted = jni_zero::ConvertArray<jni_zero::ByteArrayView>::FromJniType( env, - jni_zero::JavaParamRef<jbyteArray>(env, bytes)); - jni_zero::tests::CPPClass* convertedType_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass*, jobject>( + jni_zero::JavaParamRef<jbyteArray>(env, static_cast<jbyteArray>(bytes))); + jni_zero::tests::CPPClass* convertedType_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass*>( env, jni_zero::JavaParamRef<jobject>(env, convertedType)); - auto ret = JNI_SampleForTests_Init( + std::vector<jni_zero::ScopedJavaLocalRef<jobject>> nonConvertedArray_converted = jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::FromJniType( + env, + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(nonConvertedArray))); + auto _ret = JNI_SampleForTests_Init( env, jni_zero::JavaParamRef<jobject>(env, caller), jni_zero::JavaParamRef<jstring>(env, param), bytes_converted, - convertedType_converted); - return ret; + convertedType_converted, + nonConvertedArray_converted); + return _ret; } JNI_BOUNDARY_EXPORT void Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1iterateAndDoSomethingWithStructB( @@ -199,9 +205,9 @@ jclass jcaller, jlong nativeCPPClass, jobject caller) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB") - native->IterateAndDoSomethingWithStructB( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "IterateAndDoSomethingWithStructB") + _native->IterateAndDoSomethingWithStructB( env, jni_zero::JavaParamRef<jobject>(env, caller)); } @@ -212,16 +218,16 @@ jlong nativeCPPClass, jobject caller, jobjectArray strings) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0) - std::vector<std::string> strings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType<jstring>( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "Method", 0) + std::vector<std::string> strings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, strings)); - auto ret = native->Method( + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(strings))); + auto _ret = _native->Method( env, jni_zero::JavaParamRef<jobject>(env, caller), strings_converted); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jdouble Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1methodOtherP0( @@ -229,12 +235,12 @@ jclass jcaller, jlong nativePtr, jobject caller) { - CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); - CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0) - auto ret = native->MethodOtherP0( + CPPClass::InnerClass* _native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); + CHECK_NATIVE_PTR(env, jcaller, _native, "MethodOtherP0", 0) + auto _ret = _native->MethodOtherP0( env, jni_zero::JavaParamRef<jobject>(env, caller)); - return ret; + return _ret; } JNI_BOUNDARY_EXPORT jstring Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1returnAString( @@ -242,28 +248,28 @@ jclass jcaller, jlong nativeCPPClass, jobject caller) { - CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); - CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", nullptr) - auto ret = native->ReturnAString( + CPPClass* _native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, _native, "ReturnAString", nullptr) + auto _ret = _native->ReturnAString( env, jni_zero::JavaParamRef<jobject>(env, caller)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. static void JNI_SampleForTests_SetNonPODDatatype( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& caller, + const jni_zero::JavaParamRef<jobject>& obj, const jni_zero::JavaParamRef<jobject>& rect); JNI_BOUNDARY_EXPORT void Java_this_is_a_package_prefix_org_jni_1zero_GEN_1JNI_this_1is_1a_1package_1prefix_1org_1jni_11zero_1SampleForTests_1setNonPODDatatype( JNIEnv* env, jclass jcaller, - jobject caller, + jobject obj, jobject rect) { JNI_SampleForTests_SetNonPODDatatype( env, - jni_zero::JavaParamRef<jobject>(env, caller), + jni_zero::JavaParamRef<jobject>(env, obj), jni_zero::JavaParamRef<jobject>(env, rect)); } @@ -282,12 +288,12 @@ "<init>", "(II)V", &cached_method_id); - auto ret = env->NewObject( + auto _ret = env->NewObject( clazz, call_context.method_id(), as_jint(foo), as_jint(bar)); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static void Java_SampleForTests_addStructA( @@ -321,12 +327,12 @@ "getClass", "(Ljava/lang/Class;)Ljava/lang/Class;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), arg0.obj()); - jclass ret2 = static_cast<jclass>(ret); - return jni_zero::ScopedJavaLocalRef<jclass>(env, ret2); + jclass _ret2 = static_cast<jclass>(_ret); + return jni_zero::ScopedJavaLocalRef<jclass>(env, _ret2); } static std::string Java_SampleForTests_getFirstString( @@ -344,22 +350,21 @@ "getFirstString", "([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", &cached_method_id); - jni_zero::ScopedJavaLocalRef<jobjectArray> array_converted = jni_zero::ConvertArray<std::vector<const char*>>::ToJniType<jstring>( + jni_zero::ScopedJavaLocalRef<jobject> converted_array = jni_zero::ConvertArray<std::vector<const char*>>::ToJniType( env, array, jni_zero::g_string_class); - jni_zero::ScopedJavaLocalRef<jstring> finalArg_converted = jni_zero::ToJniType<const char*, jstring>( + jni_zero::ScopedJavaLocalRef<jobject> converted_finalArg = jni_zero::ToJniType<const char*>( env, finalArg); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), - array_converted.obj(), - finalArg_converted.obj()); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::FromJniType<std::string, jstring>( + converted_array.obj(), + converted_finalArg.obj()); + return jni_zero::FromJniType<std::string>( env, - jni_zero::JavaParamRef<jstring>(env, ret2)); + jni_zero::JavaParamRef<jobject>(env, _ret)); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum( @@ -374,8 +379,8 @@ "getInnerEnum", "()Lthis/is/a/package/prefix/org/jni_zero/SampleForTests$InnerEnum;", &cached_method_id); - auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum( @@ -391,11 +396,11 @@ "getInnerEnum", "(I)Lthis/is/a/package/prefix/org/jni_zero/SampleForTests$InnerEnum;", &cached_method_id); - auto ret = env->CallStaticObjectMethod( + auto _ret = env->CallStaticObjectMethod( clazz, call_context.method_id(), as_jint(a)); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerInterface( @@ -410,8 +415,8 @@ "getInnerInterface", "()Lthis/is/a/package/prefix/org/jni_zero/SampleForTests$InnerInterface;", &cached_method_id); - auto ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + auto _ret = env->CallStaticObjectMethod(clazz, call_context.method_id()); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jni_zero::ScopedJavaLocalRef<jthrowable> Java_SampleForTests_getThrowable( @@ -428,12 +433,12 @@ "getThrowable", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", &cached_method_id); - auto ret = env->CallObjectMethod( + auto _ret = env->CallObjectMethod( obj.obj(), call_context.method_id(), arg0.obj()); - jthrowable ret2 = static_cast<jthrowable>(ret); - return jni_zero::ScopedJavaLocalRef<jthrowable>(env, ret2); + jthrowable _ret2 = static_cast<jthrowable>(_ret); + return jni_zero::ScopedJavaLocalRef<jthrowable>(env, _ret2); } static void Java_SampleForTests_iterateAndDoSomething( @@ -455,8 +460,8 @@ static jint Java_SampleForTests_javaMethod( JNIEnv* env, const jni_zero::JavaRef<jobject>& obj, - JniIntWrapper foo, - JniIntWrapper bar) { + JniIntWrapper _jcaller, + JniIntWrapper ret) { static std::atomic<jmethodID> cached_method_id(nullptr); jclass clazz = this_is_a_package_prefix_org_jni_1zero_SampleForTests_clazz(env); CHECK_CLAZZ(env, obj.obj(), clazz, 0); @@ -467,12 +472,12 @@ "javaMethod", "(II)I", &cached_method_id); - auto ret = env->CallIntMethod( + auto _ret = env->CallIntMethod( obj.obj(), call_context.method_id(), - as_jint(foo), - as_jint(bar)); - return ret; + as_jint(_jcaller), + as_jint(ret)); + return _ret; } static void Java_SampleForTests_javaMethodWithAnnotatedParam( @@ -492,15 +497,15 @@ "javaMethodWithAnnotatedParam", "(IIIJ)V", &cached_method_id); - jint foo_converted = static_cast<jint>(foo); - jlong bat_converted = static_cast<jlong>(bat); + jint converted_foo = static_cast<jint>(foo); + jlong converted_bat = static_cast<jlong>(bat); env->CallVoidMethod( obj.obj(), call_context.method_id(), - foo_converted, + converted_foo, as_jint(bar), as_jint(baz), - bat_converted); + converted_bat); } static void Java_SampleForTests_methodThatThrowsException( @@ -532,14 +537,14 @@ "methodWithAnnotationParamAssignment", "()Z", &cached_method_id); - auto ret = env->CallBooleanMethod(obj.obj(), call_context.method_id()); - return ret; + auto _ret = env->CallBooleanMethod(obj.obj(), call_context.method_id()); + return _ret; } static void Java_SampleForTests_methodWithGenericParams( JNIEnv* env, const jni_zero::JavaRef<jobject>& obj, - const jni_zero::JavaRef<jobject>& foo, + const jni_zero::JavaRef<jobject>& _env, const jni_zero::JavaRef<jobject>& bar) { static std::atomic<jmethodID> cached_method_id(nullptr); jclass clazz = this_is_a_package_prefix_org_jni_1zero_SampleForTests_clazz(env); @@ -554,7 +559,7 @@ env->CallVoidMethod( obj.obj(), call_context.method_id(), - foo.obj(), + _env.obj(), bar.obj()); } @@ -585,8 +590,8 @@ "staticJavaMethod", "()Z", &cached_method_id); - auto ret = env->CallStaticBooleanMethod(clazz, call_context.method_id()); - return ret; + auto _ret = env->CallStaticBooleanMethod(clazz, call_context.method_id()); + return _ret; } static jni_zero::ScopedJavaLocalRef<jobject> Java_InnerStructA_create( @@ -604,13 +609,13 @@ "create", "(JILjava/lang/String;)Lthis/is/a/package/prefix/org/jni_zero/SampleForTests$InnerStructA;", &cached_method_id); - auto ret = env->CallStaticObjectMethod( + auto _ret = env->CallStaticObjectMethod( clazz, call_context.method_id(), l, as_jint(i), s.obj()); - return jni_zero::ScopedJavaLocalRef<jobject>(env, ret); + return jni_zero::ScopedJavaLocalRef<jobject>(env, _ret); } static jlong Java_InnerStructB_getKey( @@ -626,8 +631,8 @@ "getKey", "()J", &cached_method_id); - auto ret = env->CallLongMethod(obj.obj(), call_context.method_id()); - return ret; + auto _ret = env->CallLongMethod(obj.obj(), call_context.method_id()); + return _ret; } static jni_zero::ScopedJavaLocalRef<jstring> Java_InnerStructB_getValue( @@ -643,9 +648,9 @@ "getValue", "()Ljava/lang/String;", &cached_method_id); - auto ret = env->CallObjectMethod(obj.obj(), call_context.method_id()); - jstring ret2 = static_cast<jstring>(ret); - return jni_zero::ScopedJavaLocalRef<jstring>(env, ret2); + auto _ret = env->CallObjectMethod(obj.obj(), call_context.method_id()); + jstring _ret2 = static_cast<jstring>(_ret); + return jni_zero::ScopedJavaLocalRef<jstring>(env, _ret2); }
diff --git a/third_party/jni_zero/test/golden/testPerFileNatives-SampleForAnnotationProcessor_jni.h.golden b/third_party/jni_zero/test/golden/testPerFileNatives-SampleForAnnotationProcessor_jni.h.golden index 5d192ab9..c2962131 100644 --- a/third_party/jni_zero/test/golden/testPerFileNatives-SampleForAnnotationProcessor_jni.h.golden +++ b/third_party/jni_zero/test/golden/testPerFileNatives-SampleForAnnotationProcessor_jni.h.golden
@@ -23,10 +23,10 @@ // Forward declare used conversion functions to avoid a compiler warning that // triggers if a conversion specialization exists within the including .cc file. namespace jni_zero { -template<> jni_zero::ScopedJavaLocalRef<jstring> ToJniType<std::string, jstring>(JNIEnv*, std::string const&); -template<> jni_zero::tests::CPPClass FromJniType<jni_zero::tests::CPPClass, jobject>(JNIEnv*, const JavaRef<jobject>&); -template<> std::optional<std::string> FromJniType<std::optional<std::string>, jstring>(JNIEnv*, const JavaRef<jstring>&); -template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&); +template<> jni_zero::ScopedJavaLocalRef<jobject> ToJniType<std::string>(JNIEnv*, std::string const&); +template<> jni_zero::tests::CPPClass FromJniType<jni_zero::tests::CPPClass>(JNIEnv*, const JavaRef<jobject>&); +template<> std::optional<std::string> FromJniType<std::optional<std::string>>(JNIEnv*, const JavaRef<jobject>&); +template<> std::string FromJniType<std::string>(JNIEnv*, const JavaRef<jobject>&); } // namespace jni_zero // Java to native functions // Forward declaration. To be implemented by the including .cc file. @@ -38,10 +38,10 @@ JNIEnv* env, jclass jcaller, jobject sample) { - auto ret = JNI_SampleForAnnotationProcessor_Bar( + auto _ret = JNI_SampleForAnnotationProcessor_Bar( env, jni_zero::JavaParamRef<jobject>(env, sample)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -59,8 +59,8 @@ JNI_BOUNDARY_EXPORT jboolean Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeHasPhalange( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_HasPhalange(env); - return ret; + auto _ret = JNI_SampleForAnnotationProcessor_HasPhalange(env); + return _ret; } // Forward declaration. To be implemented by the including .cc file. @@ -70,8 +70,8 @@ JNI_BOUNDARY_EXPORT jclass Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnClass( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnClass(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnClass(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -81,8 +81,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnClasses( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnClasses(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnClasses(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -93,11 +93,12 @@ JNIEnv* env, jclass jcaller, jclass __arrayClazz) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedAppObjects(env); - return jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::ToJniType<jobject>( + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedAppObjects(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<jni_zero::ScopedJavaLocalRef<jobject>>>::ToJniType( env, - ret, + _ret, __arrayClazz).Release(); + return static_cast<jobjectArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -107,8 +108,11 @@ JNI_BOUNDARY_EXPORT jintArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnConvertedInts( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedInts(env); - return jni_zero::ConvertArray<std::vector<jint>>::ToJniType(env, ret).Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedInts(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<jint>>::ToJniType( + env, + _ret).Release(); + return static_cast<jintArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -118,8 +122,9 @@ JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnConvertedString( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedString(env); - return jni_zero::ToJniType<std::string, jstring>(env, ret).Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedString(env); + jobject converted_ret = jni_zero::ToJniType<std::string>(env, _ret).Release(); + return static_cast<jstring>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -129,11 +134,12 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnConvertedStrings( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnConvertedStrings(env); - return jni_zero::ConvertArray<std::vector<std::string>>::ToJniType<jstring>( + auto _ret = JNI_SampleForAnnotationProcessor_ReturnConvertedStrings(env); + jobject converted_ret = jni_zero::ConvertArray<std::vector<std::string>>::ToJniType( env, - ret, + _ret, jni_zero::g_string_class).Release(); + return static_cast<jobjectArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -143,8 +149,8 @@ JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnObject( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnObject(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnObject(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -154,8 +160,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnObjects( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnObjects(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnObjects(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -165,8 +171,8 @@ JNI_BOUNDARY_EXPORT jstring Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnString( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnString(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnString(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -176,8 +182,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnStrings( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStrings(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStrings(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -187,8 +193,8 @@ JNI_BOUNDARY_EXPORT jobject Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnStruct( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStruct(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStruct(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -198,8 +204,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnStructs( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnStructs(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnStructs(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -209,8 +215,8 @@ JNI_BOUNDARY_EXPORT jthrowable Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnThrowable( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnThrowable(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnThrowable(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -220,8 +226,8 @@ JNI_BOUNDARY_EXPORT jobjectArray Java_org_jni_1zero_SampleForAnnotationProcessorJni_nativeReturnThrowables( JNIEnv* env, jclass jcaller) { - auto ret = JNI_SampleForAnnotationProcessor_ReturnThrowables(env); - return ret.Release(); + auto _ret = JNI_SampleForAnnotationProcessor_ReturnThrowables(env); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -233,10 +239,10 @@ JNIEnv* env, jclass jcaller, jstring stringToReverse) { - auto ret = JNI_SampleForAnnotationProcessor_RevString( + auto _ret = JNI_SampleForAnnotationProcessor_RevString( env, jni_zero::JavaParamRef<jstring>(env, stringToReverse)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -248,10 +254,10 @@ JNIEnv* env, jclass jcaller, jobjectArray strs) { - auto ret = JNI_SampleForAnnotationProcessor_SendSamplesToNative( + auto _ret = JNI_SampleForAnnotationProcessor_SendSamplesToNative( env, jni_zero::JavaParamRef<jobjectArray>(env, strs)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -263,10 +269,10 @@ JNIEnv* env, jclass jcaller, jobjectArray strs) { - auto ret = JNI_SampleForAnnotationProcessor_SendToNative( + auto _ret = JNI_SampleForAnnotationProcessor_SendToNative( env, jni_zero::JavaParamRef<jobjectArray>(env, strs)); - return ret.Release(); + return _ret.Release(); } // Forward declaration. To be implemented by the including .cc file. @@ -311,9 +317,9 @@ int zint_converted = static_cast<int>(zint); std::vector<int32_t> ints_converted = jni_zero::ConvertArray<std::vector<int32_t>>::FromJniType( env, - jni_zero::JavaParamRef<jintArray>(env, ints)); + jni_zero::JavaParamRef<jintArray>(env, static_cast<jintArray>(ints))); int zchar_converted = static_cast<int>(zchar); - auto ret = JNI_SampleForAnnotationProcessor_TestAllPrimitives( + auto _ret = JNI_SampleForAnnotationProcessor_TestAllPrimitives( env, zint_converted, ints_converted, @@ -331,7 +337,10 @@ jni_zero::JavaParamRef<jfloatArray>(env, floats), zbool, jni_zero::JavaParamRef<jbooleanArray>(env, bools)); - return jni_zero::ConvertArray<std::vector<int32_t>>::ToJniType(env, ret).Release(); + jobject converted_ret = jni_zero::ConvertArray<std::vector<int32_t>>::ToJniType( + env, + _ret).Release(); + return static_cast<jintArray>(converted_ret); } // Forward declaration. To be implemented by the including .cc file. @@ -377,21 +386,21 @@ jobject view, jobject context, jobjectArray convertedObjects) { - std::string convertedString_converted = jni_zero::FromJniType<std::string, jstring>( + std::string convertedString_converted = jni_zero::FromJniType<std::string>( env, - jni_zero::JavaParamRef<jstring>(env, convertedString)); - std::vector<std::string> convertedStrings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType<jstring>( + jni_zero::JavaParamRef<jobject>(env, convertedString)); + std::vector<std::string> convertedStrings_converted = jni_zero::ConvertArray<std::vector<std::string>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, convertedStrings)); - std::optional<std::string> optionalString_converted = jni_zero::FromJniType<std::optional<std::string>, jstring>( + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(convertedStrings))); + std::optional<std::string> optionalString_converted = jni_zero::FromJniType<std::optional<std::string>>( env, - jni_zero::JavaParamRef<jstring>(env, optionalString)); - jni_zero::tests::CPPClass convertedObj_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass, jobject>( + jni_zero::JavaParamRef<jobject>(env, optionalString)); + jni_zero::tests::CPPClass convertedObj_converted = jni_zero::FromJniType<jni_zero::tests::CPPClass>( env, jni_zero::JavaParamRef<jobject>(env, convertedObj)); - std::vector<jni_zero::tests::CPPClass> convertedObjects_converted = jni_zero::ConvertArray<std::vector<jni_zero::tests::CPPClass>>::FromJniType<jobject>( + std::vector<jni_zero::tests::CPPClass> convertedObjects_converted = jni_zero::ConvertArray<std::vector<jni_zero::tests::CPPClass>>::FromJniType( env, - jni_zero::JavaParamRef<jobjectArray>(env, convertedObjects)); + jni_zero::JavaParamRef<jobjectArray>(env, static_cast<jobjectArray>(convertedObjects))); JNI_SampleForAnnotationProcessor_TestSpecialTypes( env, jni_zero::JavaParamRef<jclass>(env, clazz),
diff --git a/third_party/jni_zero/test/golden/testPlaceholdersOverlapping-TinySample_jni.h.golden b/third_party/jni_zero/test/golden/testPlaceholdersOverlapping-TinySample_jni.h.golden index 1bc0a63..bc2d16c 100644 --- a/third_party/jni_zero/test/golden/testPlaceholdersOverlapping-TinySample_jni.h.golden +++ b/third_party/jni_zero/test/golden/testPlaceholdersOverlapping-TinySample_jni.h.golden
@@ -18,8 +18,8 @@ JNIEnv* env, jclass jcaller, jint a) { - auto ret = JNI_TinySample_Bar(env, a); - return ret; + auto _ret = JNI_TinySample_Bar(env, a); + return _ret; } // Forward declaration. To be implemented by the including .cc file.
diff --git a/third_party/jni_zero/test/golden/testUniqueAnnotations-SampleUniqueAnnotations_jni.h.golden b/third_party/jni_zero/test/golden/testUniqueAnnotations-SampleUniqueAnnotations_jni.h.golden index 0982bd62..abc21e67 100644 --- a/third_party/jni_zero/test/golden/testUniqueAnnotations-SampleUniqueAnnotations_jni.h.golden +++ b/third_party/jni_zero/test/golden/testUniqueAnnotations-SampleUniqueAnnotations_jni.h.golden
@@ -23,7 +23,7 @@ // Forward declare used conversion functions to avoid a compiler warning that // triggers if a conversion specialization exists within the including .cc file. namespace jni_zero { -template<> std::string FromJniType<std::string, jstring>(JNIEnv*, const JavaRef<jstring>&); +template<> std::string FromJniType<std::string>(JNIEnv*, const JavaRef<jobject>&); } // namespace jni_zero // Java to native functions // Forward declaration. To be implemented by the including .cc file. @@ -34,8 +34,8 @@ jclass jcaller, jint x, jint y) { - auto ret = JNI_SampleUniqueAnnotations_Bar(env, x, y); - return ret; + auto _ret = JNI_SampleUniqueAnnotations_Bar(env, x, y); + return _ret; } JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_GEN_1JNI_org_1jni_11zero_1SampleUniqueAnnotations_1foo( @@ -43,21 +43,21 @@ jclass jcaller, jlong nativePtr, jstring arg) { - FooAndroid::BarDelegate* native = reinterpret_cast<FooAndroid::BarDelegate*>(nativePtr); - CHECK_NATIVE_PTR(env, jcaller, native, "Foo") - std::string arg_converted = jni_zero::FromJniType<std::string, jstring>( + FooAndroid::BarDelegate* _native = reinterpret_cast<FooAndroid::BarDelegate*>(nativePtr); + CHECK_NATIVE_PTR(env, jcaller, _native, "Foo") + std::string arg_converted = jni_zero::FromJniType<std::string>( env, - jni_zero::JavaParamRef<jstring>(env, arg)); - native->Foo(env, arg_converted); + jni_zero::JavaParamRef<jobject>(env, arg)); + _native->Foo(env, arg_converted); } JNI_BOUNDARY_EXPORT void Java_org_jni_1zero_SampleUniqueAnnotations_nativeCallWithQualifiedObject( JNIEnv* env, jobject jcaller, jlong nativePtr) { - Foo::Bar* native = reinterpret_cast<Foo::Bar*>(nativePtr); - CHECK_NATIVE_PTR(env, jcaller, native, "CallWithQualifiedObject") - native->CallWithQualifiedObject( + Foo::Bar* _native = reinterpret_cast<Foo::Bar*>(nativePtr); + CHECK_NATIVE_PTR(env, jcaller, _native, "CallWithQualifiedObject") + _native->CallWithQualifiedObject( env, jni_zero::JavaParamRef<jobject>(env, jcaller)); }
diff --git a/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java b/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java index fe6240e..d19f5f99 100644 --- a/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java +++ b/third_party/jni_zero/test/java/src/org/jni_zero/SampleForTests.java
@@ -39,7 +39,7 @@ public void startExample() { // Calls C++ Init(...) method and holds a pointer to the C++ class. - mNativeCPPObject = SampleForTestsJni.get().init(this, "myParam", new byte[0], null); + mNativeCPPObject = SampleForTestsJni.get().init(this, "myParam", new byte[0], null, null); } public void doStuff() { @@ -68,7 +68,7 @@ // Java_SampleForTests_javaMethod(JNIEnv* env, jobject caller, jint foo, jint bar) // Typically the C++ code would have obtained the jobject via the Init() call described above. @CalledByNative - public int javaMethod(int foo, int bar) { + public int javaMethod(int jcaller, int ret) { return 0; } @@ -100,7 +100,7 @@ // Method signature with generics in params. @CalledByNative public void methodWithGenericParams( - Map<String, Map<String, String>> foo, LinkedList<Integer> bar) {} + Map<String, Map<String, String>> env, LinkedList<Integer> bar) {} // Constructors will be exported to C++ as: // Java_SampleForTests_Constructor(JNIEnv* env, jint foo, jint bar) @@ -271,7 +271,8 @@ SampleForTests caller, String param, @JniType("jni_zero::ByteArrayView") byte[] bytes, - @JniType("jni_zero::tests::CPPClass*") SampleForTests convertedType); + @JniType("jni_zero::tests::CPPClass*") SampleForTests convertedType, + @JniType("std::vector") SampleForTests[] nonConvertedArray); // This defines a function binding to the associated C++ class member function. The name is // derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e. @@ -288,7 +289,7 @@ // This declares a C++ function which the application code must implement: // static jdouble GetDoubleFunction(JNIEnv* env, jobject caller); // The jobject parameter refers back to this java side object instance. - double getDoubleFunction(SampleForTests caller); + double getDoubleFunction(SampleForTests ret); // Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather // than jobject param, as the function is declared static. @@ -297,17 +298,17 @@ // This function takes a non-POD datatype. We have a list mapping them to their full // classpath in jni_generator.py JavaParamToJni. If you require a new datatype, make sure // you add to that function. - void setNonPODDatatype(SampleForTests caller, Rect rect); + void setNonPODDatatype(SampleForTests obj, Rect rect); // This declares a C++ function which the application code must implement: // static ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, jobject caller); // The jobject parameter refers back to this java side object instance. // Note that it returns a ScopedJavaLocalRef<jobject> so that you don' have to worry about // deleting the JNI local reference. This is similar with Strings and arrays. - Object getNonPODDatatype(SampleForTests caller); + Object getNonPODDatatype(SampleForTests jcaller); // Test jclass and jthrowable, as well as generics. - Class<Map<String, String>> getClass(Class<Map<String, String>> arg0); + Class<Map<String, String>> getClass(Class<Map<String, String>> env); Throwable getThrowable(Throwable arg0);
diff --git a/third_party/jni_zero/test/sample_for_tests.cc b/third_party/jni_zero/test/sample_for_tests.cc index ad9b0705..b38b82c9 100644 --- a/third_party/jni_zero/test/sample_for_tests.cc +++ b/third_party/jni_zero/test/sample_for_tests.cc
@@ -26,29 +26,28 @@ } template <> std::string FromJniType<std::string>(JNIEnv* env, - const JavaRef<jstring>& input) { + const JavaRef<jobject>& input) { return {}; } template <> -ScopedJavaLocalRef<jstring> ToJniType<std::string>(JNIEnv* env, +ScopedJavaLocalRef<jobject> ToJniType<std::string>(JNIEnv* env, const std::string& input) { return {}; } template <> std::u16string FromJniType<std::u16string>(JNIEnv* env, - const JavaRef<jstring>& input) { + const JavaRef<jobject>& input) { return {}; } template <> -ScopedJavaLocalRef<jstring> ToJniType<std::u16string>( +ScopedJavaLocalRef<jobject> ToJniType<std::u16string>( JNIEnv* env, const std::u16string& input) { return {}; } template <> -ScopedJavaLocalRef<jstring> ToJniType<const char*>( - JNIEnv* env, - const char * const& input) { +ScopedJavaLocalRef<jobject> ToJniType<const char*>(JNIEnv* env, + const char* const& input) { return {}; } template <> @@ -61,7 +60,7 @@ template <> std::optional<std::string> FromJniType<std::optional<std::string>>( JNIEnv* env, - const JavaRef<jstring>& j_string) { + const JavaRef<jobject>& j_string) { if (!j_string) { return std::nullopt; } @@ -71,7 +70,7 @@ template <> std::optional<std::u16string> FromJniType<std::optional<std::u16string>>( JNIEnv* env, - const JavaRef<jstring>& j_string) { + const JavaRef<jobject>& j_string) { if (!j_string) { return std::nullopt; } @@ -133,11 +132,13 @@ } // Static free functions declared and called directly from java. -static jlong JNI_SampleForTests_Init(JNIEnv* env, - const JavaParamRef<jobject>& caller, - const JavaParamRef<jstring>& param, - jni_zero::ByteArrayView& bytes, - CPPClass* converted_type) { +static jlong JNI_SampleForTests_Init( + JNIEnv* env, + const JavaParamRef<jobject>& caller, + const JavaParamRef<jstring>& param, + jni_zero::ByteArrayView& bytes, + CPPClass* converted_type, + std::vector<jni_zero::ScopedJavaLocalRef<jobject>>& non_converted_array) { return static_cast<jlong>(bytes.size()); }
diff --git a/third_party/lens_server_proto/README.chromium b/third_party/lens_server_proto/README.chromium index ef83d2c..33785ac8 100644 --- a/third_party/lens_server_proto/README.chromium +++ b/third_party/lens_server_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Lens Protos Short Name: lens_overlay_proto URL: This is the canonical public repository -Version: 623362227 -Date: 2024-04-10 UTC +Version: 625137722 +Date: 2024-04-16 UTC License: BSD License File: LICENSE Shipped: yes
diff --git a/third_party/lens_server_proto/lens_overlay_geometry.proto b/third_party/lens_server_proto/lens_overlay_geometry.proto index dd80a72..a310dca 100644 --- a/third_party/lens_server_proto/lens_overlay_geometry.proto +++ b/third_party/lens_server_proto/lens_overlay_geometry.proto
@@ -30,7 +30,12 @@ // Specifies the bounding box for this geometry. optional CenterRotatedBox bounding_box = 1; - reserved 2, 3, 4, 5, 6; + // Specifies the segmentation polygon. The vertices of the outer-boundaries + // are in clockwise, and the ones of inner-boundaries are in counter-clockwise + // ordering. + repeated Polygon segmentation_polygon = 5; + + reserved 2, 3, 4, 6; } // A cropped and potentially re-scaled image region, rectangular subregion of a
diff --git a/third_party/lens_server_proto/lens_overlay_polygon.proto b/third_party/lens_server_proto/lens_overlay_polygon.proto index dcac5bcb..77a1545 100644 --- a/third_party/lens_server_proto/lens_overlay_polygon.proto +++ b/third_party/lens_server_proto/lens_overlay_polygon.proto
@@ -17,3 +17,24 @@ // Image pixel coordinates. IMAGE = 2; } + +// Information about a polygon. +message Polygon { + // Represents a single vertex in the polygon. + message Vertex { + optional float x = 1; + optional float y = 2; + } + repeated Vertex vertex = 1; + + // Specifies the vertex ordering. + enum VertexOrdering { + VERTEX_ORDERING_UNSPECIFIED = 0; + CLOCKWISE = 1; + COUNTER_CLOCKWISE = 2; + } + optional VertexOrdering vertex_ordering = 2; + + // Specifies the coordinate type of vertices. + optional CoordinateType coordinate_type = 3; +}
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index b30ee9e..364c7c7 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -1,7 +1,7 @@ Name: libvpx URL: https://chromium.googlesource.com/webm/libvpx Version: N/A -Revision: 8762f5efb2917765316a198e6713f0bc93b07c9b +Revision: 85dafa9c61f99330f484e77297684b42af6ff37d CPEPrefix: cpe:/a:webmproject:libvpx:1.14.0 License: BSD License File: source/libvpx/LICENSE
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 8eae539f..3972d777 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,8 +2,8 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 14 #define VERSION_PATCH 0 -#define VERSION_EXTRA "238-g8762f5efb" +#define VERSION_EXTRA "248-g85dafa9c6" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.14.0-238-g8762f5efb" -#define VERSION_STRING " v1.14.0-238-g8762f5efb" +#define VERSION_STRING_NOSP "v1.14.0-248-g85dafa9c6" +#define VERSION_STRING " v1.14.0-248-g85dafa9c6"
diff --git a/third_party/libvpx/source/libvpx b/third_party/libvpx/source/libvpx index 8762f5e..85dafa9 160000 --- a/third_party/libvpx/source/libvpx +++ b/third_party/libvpx/source/libvpx
@@ -1 +1 @@ -Subproject commit 8762f5efb2917765316a198e6713f0bc93b07c9b +Subproject commit 85dafa9c61f99330f484e77297684b42af6ff37d
diff --git a/third_party/lit/v3_0/BUILD.gn b/third_party/lit/v3_0/BUILD.gn index f1173706..0909eb3 100644 --- a/third_party/lit/v3_0/BUILD.gn +++ b/third_party/lit/v3_0/BUILD.gn
@@ -18,6 +18,7 @@ # - tests that need to refer to CrLitElement. # - a few chrome/browser/resources/ folders that hold small UIs. # Update when the migration enters its next phase. + "//chrome/browser/resources/side_panel/reading_list:build_ts", "//chrome/browser/resources/welcome:build_ts", "//chrome/browser/resources/whats_new:build_ts", "//chrome/test/data/webui/cr_elements:build_ts",
diff --git a/third_party/skia b/third_party/skia index d7f79d71..fef9f27 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit d7f79d7183cdc523e79aaac9a6b2a3da11954631 +Subproject commit fef9f270935c1b1e8cc881978d510b4a5d13fdc9
diff --git a/third_party/swiftshader b/third_party/swiftshader index 764410d..9aec4b9 160000 --- a/third_party/swiftshader +++ b/third_party/swiftshader
@@ -1 +1 @@ -Subproject commit 764410d4d65546fd1e536b02059b1f714a390720 +Subproject commit 9aec4b969291f0a218b537f44f8a1387cf494316
diff --git a/third_party/unrar/patches/chromium_changes.patch b/third_party/unrar/patches/chromium_changes.patch index 5d54a4d..f5d55428 100644 --- a/third_party/unrar/patches/chromium_changes.patch +++ b/third_party/unrar/patches/chromium_changes.patch
@@ -499,67 +499,26 @@ // How many times every modifier character was encountered in the mask. diff --git a/third_party/unrar/src/secpassword.cpp b/third_party/unrar/src/secpassword.cpp -index 08da549721649..0eac41319704b 100644 +index 08da549721649..fb90ad1675847 100644 --- a/third_party/unrar/src/secpassword.cpp +++ b/third_party/unrar/src/secpassword.cpp -@@ -25,6 +25,7 @@ class CryptLoader - } - ~CryptLoader() - { -+ // We need to call FreeLibrary when RAR is exiting. - if (hCrypt!=NULL) - FreeLibrary(hCrypt); - hCrypt=NULL; -@@ -46,12 +47,14 @@ class CryptLoader - } - } - -+ static CryptLoader& GetInstance() { -+ static CryptLoader cryptLoader; -+ return cryptLoader; -+ } -+ - CRYPTPROTECTMEMORY pCryptProtectMemory; - CRYPTUNPROTECTMEMORY pCryptUnprotectMemory; - }; -- --// We need to call FreeLibrary when RAR is exiting. --static CryptLoader GlobalCryptLoader; - #endif - - SecPassword::SecPassword() -@@ -171,15 +174,15 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) +@@ -1,6 +1,6 @@ + #include "rar.hpp" + +-#if defined(_WIN_ALL) ++#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) + typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); + typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); + +@@ -169,7 +169,7 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) + { + // CryptProtectMemory is not available in UWP and CryptProtectData // increases data size not allowing in place conversion. - #if defined(_WIN_ALL) +-#if defined(_WIN_ALL) ++#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) // Try to utilize the secure Crypt[Un]ProtectMemory if possible. -- if (GlobalCryptLoader.pCryptProtectMemory==NULL) -- GlobalCryptLoader.Load(); -+ if (CryptLoader::GetInstance().pCryptProtectMemory==NULL) -+ CryptLoader::GetInstance().Load(); - size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE; - DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS; - if (Encode) - { -- if (GlobalCryptLoader.pCryptProtectMemory!=NULL) -+ if (CryptLoader::GetInstance().pCryptProtectMemory!=NULL) - { -- if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags)) -+ if (!CryptLoader::GetInstance().pCryptProtectMemory(Data,DWORD(Aligned),Flags)) - { - ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed"); - ErrHandler.SysErrMsg(); -@@ -190,9 +193,9 @@ void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) - } - else - { -- if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL) -+ if (CryptLoader::GetInstance().pCryptUnprotectMemory!=NULL) - { -- if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) -+ if (!CryptLoader::GetInstance().pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) - { - ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed"); - ErrHandler.SysErrMsg(); + if (GlobalCryptLoader.pCryptProtectMemory==NULL) + GlobalCryptLoader.Load(); diff --git a/third_party/unrar/src/strfn.cpp b/third_party/unrar/src/strfn.cpp index 7617f7a599594..d431b3bb96d50 100644 --- a/third_party/unrar/src/strfn.cpp
diff --git a/third_party/unrar/src/secpassword.cpp b/third_party/unrar/src/secpassword.cpp index 0eac413..fb90ad167 100644 --- a/third_party/unrar/src/secpassword.cpp +++ b/third_party/unrar/src/secpassword.cpp
@@ -1,6 +1,6 @@ #include "rar.hpp" -#if defined(_WIN_ALL) +#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) typedef BOOL (WINAPI *CRYPTPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFlags); @@ -25,7 +25,6 @@ } ~CryptLoader() { - // We need to call FreeLibrary when RAR is exiting. if (hCrypt!=NULL) FreeLibrary(hCrypt); hCrypt=NULL; @@ -47,14 +46,12 @@ } } - static CryptLoader& GetInstance() { - static CryptLoader cryptLoader; - return cryptLoader; - } - CRYPTPROTECTMEMORY pCryptProtectMemory; CRYPTUNPROTECTMEMORY pCryptUnprotectMemory; }; + +// We need to call FreeLibrary when RAR is exiting. +static CryptLoader GlobalCryptLoader; #endif SecPassword::SecPassword() @@ -172,17 +169,17 @@ { // CryptProtectMemory is not available in UWP and CryptProtectData // increases data size not allowing in place conversion. -#if defined(_WIN_ALL) +#if defined(_WIN_ALL) && !defined(CHROMIUM_UNRAR) // Try to utilize the secure Crypt[Un]ProtectMemory if possible. - if (CryptLoader::GetInstance().pCryptProtectMemory==NULL) - CryptLoader::GetInstance().Load(); + if (GlobalCryptLoader.pCryptProtectMemory==NULL) + GlobalCryptLoader.Load(); size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE; DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS; if (Encode) { - if (CryptLoader::GetInstance().pCryptProtectMemory!=NULL) + if (GlobalCryptLoader.pCryptProtectMemory!=NULL) { - if (!CryptLoader::GetInstance().pCryptProtectMemory(Data,DWORD(Aligned),Flags)) + if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags)) { ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed"); ErrHandler.SysErrMsg(); @@ -193,9 +190,9 @@ } else { - if (CryptLoader::GetInstance().pCryptUnprotectMemory!=NULL) + if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL) { - if (!CryptLoader::GetInstance().pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) + if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) { ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed"); ErrHandler.SysErrMsg();
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index aa20d19..707349d 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit aa20d192b8c4e4a617d93d809cc416e0429acacd +Subproject commit 707349d2ea9e104986b12655c944c6f758a2443b
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src index 48e5f93..a2897c3 160000 --- a/third_party/webgpu-cts/src +++ b/third_party/webgpu-cts/src
@@ -1 +1 @@ -Subproject commit 48e5f9383b4c9c94a46563c59b3049705f668096 +Subproject commit a2897c33ec90d37cbfefed3b3f738f785850c6bf
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt index dbd0e4e..3375ebb 100644 --- a/third_party/webgpu-cts/ts_sources.txt +++ b/third_party/webgpu-cts/ts_sources.txt
@@ -723,6 +723,7 @@ src/webgpu/shader/validation/expression/precedence.spec.ts src/webgpu/shader/validation/expression/access/array.spec.ts src/webgpu/shader/validation/expression/access/matrix.spec.ts +src/webgpu/shader/validation/expression/access/structure.spec.ts src/webgpu/shader/validation/expression/access/vector.spec.ts src/webgpu/shader/validation/expression/call/builtin/const_override_validation.ts src/webgpu/shader/validation/expression/binary/result_type.ts @@ -757,6 +758,7 @@ src/webgpu/shader/validation/expression/call/builtin/derivatives.spec.ts src/webgpu/shader/validation/expression/call/builtin/determinant.spec.ts src/webgpu/shader/validation/expression/call/builtin/distance.spec.ts +src/webgpu/shader/validation/expression/call/builtin/dot.spec.ts src/webgpu/shader/validation/expression/call/builtin/dot4I8Packed.spec.ts src/webgpu/shader/validation/expression/call/builtin/dot4U8Packed.spec.ts src/webgpu/shader/validation/expression/call/builtin/exp.spec.ts @@ -766,6 +768,7 @@ src/webgpu/shader/validation/expression/call/builtin/firstLeadingBit.spec.ts src/webgpu/shader/validation/expression/call/builtin/firstTrailingBit.spec.ts src/webgpu/shader/validation/expression/call/builtin/floor.spec.ts +src/webgpu/shader/validation/expression/call/builtin/fma.spec.ts src/webgpu/shader/validation/expression/call/builtin/fract.spec.ts src/webgpu/shader/validation/expression/call/builtin/frexp.spec.ts src/webgpu/shader/validation/expression/call/builtin/insertBits.spec.ts @@ -805,9 +808,13 @@ src/webgpu/shader/validation/expression/call/builtin/step.spec.ts src/webgpu/shader/validation/expression/call/builtin/tan.spec.ts src/webgpu/shader/validation/expression/call/builtin/tanh.spec.ts +src/webgpu/shader/validation/expression/call/builtin/textureDimensions.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureGather.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureGatherCompare.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureLoad.spec.ts +src/webgpu/shader/validation/expression/call/builtin/textureNumLayers.spec.ts +src/webgpu/shader/validation/expression/call/builtin/textureNumLevels.spec.ts +src/webgpu/shader/validation/expression/call/builtin/textureNumSamples.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureSample.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureSampleBaseClampToEdge.spec.ts src/webgpu/shader/validation/expression/call/builtin/textureSampleBias.spec.ts @@ -850,6 +857,7 @@ src/webgpu/shader/validation/parse/compound.spec.ts src/webgpu/shader/validation/parse/const.spec.ts src/webgpu/shader/validation/parse/const_assert.spec.ts +src/webgpu/shader/validation/parse/continue.spec.ts src/webgpu/shader/validation/parse/continuing.spec.ts src/webgpu/shader/validation/parse/diagnostic.spec.ts src/webgpu/shader/validation/parse/discard.spec.ts @@ -886,6 +894,7 @@ src/webgpu/shader/validation/shader_io/locations.spec.ts src/webgpu/shader/validation/shader_io/size.spec.ts src/webgpu/shader/validation/shader_io/workgroup_size.spec.ts +src/webgpu/shader/validation/statement/test_types.ts src/webgpu/shader/validation/statement/break_if.spec.ts src/webgpu/shader/validation/statement/for.spec.ts src/webgpu/shader/validation/statement/if.spec.ts
diff --git a/third_party/webrtc b/third_party/webrtc index 56e6309..ff54aee 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 56e63097498d0ad6fe2eca779b7df173cc6a0fca +Subproject commit ff54aee9ab3d5fc5ea6f9d12fb05c582115b736d
diff --git a/tools/bisect/bisect_builds.py b/tools/bisect/bisect_builds.py new file mode 100755 index 0000000..9f6fd82 --- /dev/null +++ b/tools/bisect/bisect_builds.py
@@ -0,0 +1,1971 @@ +#!/usr/bin/env python3 +# 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. + +"""Snapshot Build Bisect Tool + +This script bisects a snapshot archive using binary search. It starts at +a bad revision (it will try to guess HEAD) and asks for a last known-good +revision. It will then binary search across this revision range by downloading, +unzipping, and opening Chromium for you. After testing the specific revision, +it will ask you whether it is good or bad before continuing the search. +""" + +import bisect +import http.client +import importlib +import json +import optparse +import os +import platform +import re +import shlex +import shutil +import subprocess +import sys +import tempfile +import time +import threading +import traceback +import urllib.request, urllib.parse, urllib.error +from distutils.version import LooseVersion +from xml.etree import ElementTree +import zipfile + +# These constants are used for android bisect which depends on +# Catapult repo. +DEFAULT_CATAPULT_DIR = os.path.abspath(os.path.join( + os.path.dirname(__file__), 'catapult_bisect_dep')) +CATAPULT_DIR = os.environ.get('CATAPULT_DIR', DEFAULT_CATAPULT_DIR) +CATAPULT_REPO = 'https://github.com/catapult-project/catapult.git' +DEVIL_PATH = os.path.abspath(os.path.join(CATAPULT_DIR, 'devil')) + +# The base URL for stored build archives. +CHROMIUM_BASE_URL = ('http://commondatastorage.googleapis.com' + '/chromium-browser-snapshots') +WEBKIT_BASE_URL = ('http://commondatastorage.googleapis.com' + '/chromium-webkit-snapshots') +ASAN_BASE_URL = ('http://commondatastorage.googleapis.com' + '/chromium-browser-asan') + +GSUTILS_PATH = None + +# GS bucket name for perf builds +PERF_BASE_URL = 'gs://chrome-test-builds/official-by-commit' +# GS bucket name. +RELEASE_BASE_URL = 'gs://chrome-unsigned/desktop-5c0tCh' +# Base URL for downloading release builds. +GOOGLE_APIS_URL = 'commondatastorage.googleapis.com' + +# URL template for viewing changelogs between revisions. +CHANGELOG_URL = ('https://chromium.googlesource.com/chromium/src/+log/%s..%s') + +# URL to convert SVN revision to git hash. +CRREV_URL = ('https://cr-rev.appspot.com/_ah/api/crrev/v1/redirect/') + +# URL template for viewing changelogs between release versions. +RELEASE_CHANGELOG_URL = ('https://chromium.googlesource.com/chromium/' + 'src/+log/%s..%s?pretty=fuller&n=10000') + +# DEPS file URL. +DEPS_FILE_OLD = ('http://src.chromium.org/viewvc/chrome/trunk/src/' + 'DEPS?revision=%d') +DEPS_FILE_NEW = ('https://chromium.googlesource.com/chromium/src/+/%s/DEPS') + +# Blink changelogs URL. +BLINK_CHANGELOG_URL = ('http://build.chromium.org' + '/f/chromium/perf/dashboard/ui/changelog_blink.html' + '?url=/trunk&range=%d%%3A%d') + +DONE_MESSAGE_GOOD_MIN = ('You are probably looking for a change made after %s (' + 'known good), but no later than %s (first known bad).') +DONE_MESSAGE_GOOD_MAX = ('You are probably looking for a change made after %s (' + 'known bad), but no later than %s (first known good).') + +CHROMIUM_GITHASH_TO_SVN_URL = ( + 'https://chromium.googlesource.com/chromium/src/+/%s?format=json') + +BLINK_GITHASH_TO_SVN_URL = ( + 'https://chromium.googlesource.com/chromium/blink/+/%s?format=json') + +GITHASH_TO_SVN_URL = { + 'chromium': CHROMIUM_GITHASH_TO_SVN_URL, + 'blink': BLINK_GITHASH_TO_SVN_URL, +} + +VERSION_INFO_URL = ( + 'https://chromiumdash.appspot.com/fetch_version?version=%s') + +# Search pattern to be matched in the JSON output from +# CHROMIUM_GITHASH_TO_SVN_URL to get the chromium revision (svn revision). +CHROMIUM_SEARCH_PATTERN_OLD = ( + r'.*git-svn-id: svn://svn.chromium.org/chrome/trunk/src@(\d+) ') +CHROMIUM_SEARCH_PATTERN = ( + r'Cr-Commit-Position: refs/heads/master@{#(\d+)}') # nocheck + +# Search pattern to be matched in the json output from +# BLINK_GITHASH_TO_SVN_URL to get the blink revision (svn revision). +BLINK_SEARCH_PATTERN = ( + r'.*git-svn-id: svn://svn.chromium.org/blink/trunk@(\d+) ') + +SEARCH_PATTERN = { + 'chromium': CHROMIUM_SEARCH_PATTERN, + 'blink': BLINK_SEARCH_PATTERN, +} + +CREDENTIAL_ERROR_MESSAGE = ('You are attempting to access protected data with ' + 'no configured credentials') +PATH_CONTEXT = { + 'release': { + 'linux64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'linux64/', + 'archive_name': 'chrome-linux64.zip', + 'archive_extract_dir': 'chrome-linux64' + }, + 'mac': { + 'binary_name': 'Google Chrome.app/Contents/MacOS/Google Chrome', + 'listing_platform_dir': 'mac/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + 'mac64': { + 'binary_name': 'Google Chrome.app/Contents/MacOS/Google Chrome', + 'listing_platform_dir': 'mac64/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + 'mac-arm': { + 'binary_name': 'Google Chrome.app/Contents/MacOS/Google Chrome', + 'listing_platform_dir': 'mac-arm64/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + 'win-clang': { # Release builds switched to -clang in M64. + 'binary_name': 'chrome.exe', + 'listing_platform_dir': 'win-clang/', + 'archive_name': 'chrome-win-clang.zip', + 'archive_extract_dir': 'chrome-win-clang' + }, + 'win64-clang': { # Release builds switched to -clang in M64. + 'binary_name': 'chrome.exe', + 'listing_platform_dir': 'win64-clang/', + 'archive_name': 'chrome-win64-clang.zip', + 'archive_extract_dir': 'chrome-win64-clang' + }, + 'lacros64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros64/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros64' + }, + 'lacros-arm32': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros-arm32/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros-arm32' + }, + 'lacros-arm64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros-arm64/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros-arm64' + }, + }, + 'official': { + 'arm': { + 'binary_name': None, + 'listing_platform_dir': 'Android Builder/', + 'archive_name': 'chrome-perf-arm.zip', + 'archive_extract_dir': 'full-build-linux' + }, + 'linux64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'linux-builder-perf/', + 'archive_name': 'chrome-perf-linux.zip', + 'archive_extract_dir': 'full-build-linux' + }, + 'mac': { + 'binary_name': 'Google Chrome.app/Contents/MacOS/Google Chrome', + 'listing_platform_dir': 'mac-builder-perf/', + 'archive_name': 'chrome-perf-mac.zip', + 'archive_extract_dir': 'full-build-mac' + }, + 'mac-arm': { + 'binary_name': 'Google Chrome.app/Contents/MacOS/Google Chrome', + 'listing_platform_dir': 'mac-arm-builder-perf/', + 'archive_name': 'chrome-perf-mac.zip', + 'archive_extract_dir': 'full-build-mac' + }, + 'win64': { + 'binary_name': 'chrome.exe', + 'listing_platform_dir': 'win64-builder-perf/', + 'archive_name': 'chrome-perf-win.zip', + 'archive_extract_dir': 'full-build-win32' + }, + 'lacros64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'chromeos-amd64-generic-lacros-builder-perf/', + 'archive_name': 'chrome-perf-lacros64.zip', + 'archive_extract_dir': 'full-build-linux' + }, + 'lacros-arm32': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'chromeos-arm-generic-lacros-builder-perf/', + 'archive_name': 'chrome-perf-lacros-arm32.zip', + 'archive_extract_dir': 'full-build-linux' + }, + 'lacros-arm64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'chromeos-arm64-generic-lacros-builder-perf/', + 'archive_name': 'chrome-perf-lacros-arm64.zip', + 'archive_extract_dir': 'full-build-linux' + } + }, + 'snapshot': { + 'linux64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'Linux_x64/', + 'archive_name': 'chrome-linux.zip', + 'archive_extract_dir': 'chrome-linux' + }, + 'linux-arm': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'Linux_ARM_Cross-Compile/', + 'archive_name': 'chrome-linux.zip', + 'archive_extract_dir': 'chrome-linux' + }, + # Note: changed at revision 591483; see GetDownloadURL and GetLaunchPath + # below where these are patched. + 'chromeos': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'Linux_ChromiumOS_Full/', + 'archive_name': 'chrome-linux.zip', + 'archive_extract_dir': 'chrome-linux' + }, + 'mac': { + 'binary_name': 'Chromium.app/Contents/MacOS/Chromium', + 'listing_platform_dir': 'Mac/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + 'mac64': { + 'binary_name': 'Chromium.app/Contents/MacOS/Chromium', + 'listing_platform_dir': 'Mac/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + 'mac-arm': { + 'binary_name': 'Chromium.app/Contents/MacOS/Chromium', + 'listing_platform_dir': 'Mac_Arm/', + 'archive_name': 'chrome-mac.zip', + 'archive_extract_dir': 'chrome-mac' + }, + # Note: changed at revision 591483; see GetDownloadURL and GetLaunchPath + # below where these are patched. + 'win': { + 'binary_name': 'chrome.exe', + 'listing_platform_dir': 'Win/', + 'archive_name': 'chrome-win32.zip', + 'archive_extract_dir': 'chrome-win32' + }, + 'win64': { + 'binary_name': 'chrome.exe', + 'listing_platform_dir': 'Win_x64/', + 'archive_name': 'chrome-win32.zip', + 'archive_extract_dir': 'chrome-win32' + }, + 'lacros64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros64/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros64' + }, + 'lacros-arm32': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros_arm/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros-arm32' + }, + 'lacros-arm64': { + 'binary_name': 'chrome', + 'listing_platform_dir': 'lacros_arm64/', + 'archive_name': 'lacros.zip', + 'archive_extract_dir': 'chrome-lacros-arm64' + } + } +} + +# Currently we support only ChromePublic.apk produced by +# perf builders. +CHROME_APK_FILENAMES = { + 'chromium': 'ChromePublic.apk', +} + + +# Old storage locations for per CL builds +OFFICIAL_BACKUP_BUILDS = { + 'arm': { + 'listing_platform_dir': ['Android Builder/'], + }, + 'linux64': { + 'listing_platform_dir': ['Linux Builder Perf/'], + }, + 'mac': { + 'listing_platform_dir': ['Mac Builder Perf/'], + }, + 'win64': { + 'listing_platform_dir': ['Win x64 Builder Perf/'], + } +} + +# Set only during initialization. +is_verbose = False + +class BisectException(Exception): + + def __str__(self): + return '[Bisect Exception]: %s\n' % self.args[0] + + +def RunGsutilCommand(args, can_fail=False, verbose=False): + if is_verbose: + print('Running gsutil command: ' + str([sys.executable, GSUTILS_PATH] + args)) + gsutil = subprocess.Popen([sys.executable, GSUTILS_PATH] + args, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=None) + stdout_b, stderr_b = gsutil.communicate() + stdout = stdout_b.decode("utf-8") + stderr = stderr_b.decode("utf-8") + if gsutil.returncode: + if (re.findall(r'(status|ServiceException:)[ |=]40[1|3]', stderr) or + stderr.startswith(CREDENTIAL_ERROR_MESSAGE)): + print(('Follow these steps to configure your credentials and try' + ' running the bisect-builds.py again.:\n' + ' 1. Run "python3 %s config" and follow its instructions.\n' + ' 2. If you have a @google.com account, use that account.\n' + ' 3. For the project-id, just enter 0.' % GSUTILS_PATH)) + print('Warning: You might have an outdated .boto file. If this issue ' + 'persists after running `gsutil.py config`, try removing your ' + '.boto, usually located in your home directory.') + sys.exit(1) + elif can_fail: + return stderr + else: + raise Exception('Error running the gsutil command:\n%s\n%s' % (args, stderr)) + return stdout + + +class PathContext(object): + """A PathContext is used to carry the information used to construct URLs and + paths when dealing with the storage server and archives.""" + def __init__(self, options, device=None): + super(PathContext, self).__init__() + # Store off the input parameters. + self.platform = options.archive + self.good_revision = options.good + self.bad_revision = options.bad + self.is_release = options.release_builds + self.is_official = options.official_builds + self.is_asan = options.asan + self.flash_path = options.flash_path + self.build_type = 'release' + # Whether to cache and use the list of known revisions in a local file to + # speed up the initialization of the script at the next run. + self.use_local_cache = options.use_local_cache + if options.asan: + self.base_url = ASAN_BASE_URL + elif options.blink: + self.base_url = WEBKIT_BASE_URL + else: + self.base_url = CHROMIUM_BASE_URL + + self.apk = options.apk + self.device = device + + # Dictionary which stores svn revision number as key and it's + # corresponding git hash as value. This data is populated in + # _FetchAndParse and used later in GetDownloadURL while downloading + # the build. + self.githash_svn_dict = {} + # The name of the ZIP file in a revision directory on the server. + self.archive_name = None + + + # Locate the local checkout to speed up the script by using locally stored + # metadata. + abs_file_path = os.path.abspath(os.path.realpath(__file__)) + local_src_path = os.path.join(os.path.dirname(abs_file_path), '..') + if abs_file_path.endswith(os.path.join('tools', 'bisect-builds.py')) and\ + os.path.exists(os.path.join(local_src_path, '.git')): + self.local_src_path = os.path.normpath(local_src_path) + else: + self.local_src_path = None + + # Set some internal members: + # _listing_platform_dir = Directory that holds revisions. Ends with a '/'. + # _archive_extract_dir = Uncompressed directory in the archive_name file. + # _binary_name = The name of the executable to run. + self.SetPathContextMembers(self.platform) + + def SetPathContextMembers(self, platform): + if self.is_release: + test_type = 'release' + # Linux release archives changed their name during the M60 cycle, so older + # builds won't be found in the current path. + if platform == 'linux64': + # For releases, the revision # is actually a "1.2.3.4"-style version. + good_major = int(self.good_revision.split('.')[0]) + bad_major = int(self.bad_revision.split('.')[0]) + # The new path definitely doesn't exist before M57 + if min(good_major, bad_major) < 58: + print ('Linux release archives changed location during the M58 cycle,\n' + 'and older builds are currently not supported by this script.\n' + 'If you really need to bisect pre-M58 builds, please contact\n' + 'prasadv@ or mmoss@ for assistance, otherwise please re-run\n' + 'with more recent revision values.') + sys.exit(1) + if min(good_major, bad_major) < 59: + print ('-----------------------------------------------------------\n' + 'WARNING: Linux release archives changed location during the\n' + 'M58 cycle, so this bisect might be be missing some builds.\n' + 'If you really need to bisect against all M58 builds, please\n' + 'contact prasadv@ or mmoss@ for assistance.\n' + '-----------------------------------------------------------') + elif self.is_official: + test_type = 'official' + else: + test_type = 'snapshot' # default test type + path_members = PATH_CONTEXT[test_type].get(platform) + if not path_members: + raise BisectException('Error: Bisecting on %s builds are only ' + 'supported on these platforms: [%s].' % + (test_type, + '|'.join(PATH_CONTEXT[test_type].keys()))) + self._binary_name = path_members['binary_name'] + self._listing_platform_dir = path_members['listing_platform_dir'] + self.archive_name = path_members['archive_name'] + self._archive_extract_dir = path_members['archive_extract_dir'] + + def GetASANPlatformDir(self): + """ASAN builds are in directories like "linux-release", or have filenames + like "asan-win32-release-277079.zip". This aligns to our platform names + except in the case of Windows where they use "win32" instead of "win".""" + if self.platform == 'win': + return 'win32' + else: + return self.platform + + def GetListingURL(self, marker=None): + """Returns the URL for a directory listing, with an optional marker.""" + marker_param = '' + if marker: + marker_param = '&marker=' + str(marker) + if self.is_asan: + prefix = '%s-%s' % (self.GetASANPlatformDir(), self.build_type) + return self.base_url + '/?delimiter=&prefix=' + prefix + marker_param + elif self.is_official: + return (self.base_url + '/?prefix=' + + self._listing_platform_dir + marker_param) + else: + return (self.base_url + '/?delimiter=/&prefix=' + + self._listing_platform_dir + marker_param) + + def GetDownloadURL(self, revision): + """Gets the download URL for a build archive of a specific revision.""" + archive_name = self.archive_name + # At revision 591483, the names of two of the archives changed + # due to: https://chromium-review.googlesource.com/#/q/1226086 + # See: http://crbug.com/789612 + # revision passed in can either be a cr commit position(int), + # or a chrome version(str). + if '.' not in str(revision) and revision >= 591483: + if self.platform == 'chromeos': + archive_name = 'chrome-chromeos.zip' + elif self.platform in ('win', 'win64'): + archive_name = 'chrome-win.zip' + + if self.is_asan: + return '%s/%s-%s/%s-%d.zip' % ( + ASAN_BASE_URL, self.GetASANPlatformDir(), self.build_type, + self.GetASANBaseName(), revision) + if self.is_release: + return '%s/%s/%s%s' % ( + RELEASE_BASE_URL, revision, self._listing_platform_dir, + archive_name) + if self.is_official: + return '%s/%s%s_%s.zip' % ( + PERF_BASE_URL, self._listing_platform_dir, self._archive_extract_dir, + revision) + + else: + if str(revision) in self.githash_svn_dict: + revision = self.githash_svn_dict[str(revision)] + return '%s/%s%s/%s' % (self.base_url, self._listing_platform_dir, + revision, archive_name) + + def GetLastChangeURL(self): + """Returns a URL to the LAST_CHANGE file.""" + return self.base_url + '/' + self._listing_platform_dir + 'LAST_CHANGE' + + def GetASANBaseName(self): + """Returns the base name of the ASAN zip file.""" + if 'linux' in self.platform: + return 'asan-symbolized-%s-%s' % (self.GetASANPlatformDir(), + self.build_type) + else: + return 'asan-%s-%s' % (self.GetASANPlatformDir(), self.build_type) + + def GetLaunchPath(self, revision): + """Returns a relative path (presumably from the archive extraction location) + that is used to run the executable.""" + if self.is_asan: + extract_dir = '%s-%d' % (self.GetASANBaseName(), revision) + elif self.is_official: + extract_dir = '%s_%s' %(self._archive_extract_dir, revision) + else: + extract_dir = self._archive_extract_dir + # At revision 591483, the names of two of the archives changed + # due to: https://chromium-review.googlesource.com/#/q/1226086 + # See: http://crbug.com/789612 + if '.' not in str(revision) and revision >= 591483: + if self.platform == 'chromeos': + extract_dir = 'chrome-chromeos' + elif self.platform in ('win', 'win64'): + extract_dir = 'chrome-win' + + return os.path.join(extract_dir, self._binary_name) + + def ParseDirectoryIndex(self, last_known_rev): + """Parses the Google Storage directory listing into a list of revision + numbers.""" + + def _GetMarkerForRev(revision): + if self.is_asan: + return '%s-%s/%s-%d.zip' % ( + self.GetASANPlatformDir(), self.build_type, + self.GetASANBaseName(), revision) + return '%s%d' % (self._listing_platform_dir, revision) + + def _FetchAndParse(url): + """Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If + next-marker is not None, then the listing is a partial listing and another + fetch should be performed with next-marker being the marker= GET + parameter.""" + handle = urllib.request.urlopen(url) + document = ElementTree.parse(handle) + + # All nodes in the tree are namespaced. Get the root's tag name to extract + # the namespace. Etree does namespaces as |{namespace}tag|. + root_tag = document.getroot().tag + end_ns_pos = root_tag.find('}') + if end_ns_pos == -1: + raise Exception('Could not locate end namespace for directory index') + namespace = root_tag[:end_ns_pos + 1] + + # Find the prefix (_listing_platform_dir) and whether or not the list is + # truncated. + prefix_len = len(document.find(namespace + 'Prefix').text) + next_marker = None + is_truncated = document.find(namespace + 'IsTruncated') + if is_truncated is not None and is_truncated.text.lower() == 'true': + next_marker = document.find(namespace + 'NextMarker').text + # Get a list of all the revisions. + revisions = [] + githash_svn_dict = {} + if self.is_asan: + asan_regex = re.compile(r'.*%s-(\d+)\.zip$' % (self.GetASANBaseName())) + # Non ASAN builds are in a <revision> directory. The ASAN builds are + # flat + all_prefixes = document.findall(namespace + 'Contents/' + + namespace + 'Key') + for prefix in all_prefixes: + m = asan_regex.match(prefix.text) + if m: + try: + revisions.append(int(m.group(1))) + except ValueError: + pass + else: + all_prefixes = document.findall(namespace + 'CommonPrefixes/' + + namespace + 'Prefix') + # The <Prefix> nodes have content of the form of + # |_listing_platform_dir/revision/|. Strip off the platform dir and the + # trailing slash to just have a number.go + for prefix in all_prefixes: + revnum = prefix.text[prefix_len:-1] + try: + revnum = int(revnum) + revisions.append(revnum) + # Notes: + # Ignore hash in chromium-browser-snapshots as they are invalid + # Resulting in 404 error in fetching pages: + # https://chromium.googlesource.com/chromium/src/+/[rev_hash] + except ValueError: + pass + return (revisions, next_marker, githash_svn_dict) + + # Fetch the first list of revisions. + if last_known_rev: + revisions = [] + # Optimization: Start paging at the last known revision (local cache). + next_marker = _GetMarkerForRev(last_known_rev) + # Optimization: Stop paging at the last known revision (remote). + last_change_rev = GetChromiumRevision(self, self.GetLastChangeURL()) + if last_known_rev == last_change_rev: + return [] + else: + (revisions, next_marker, new_dict) = _FetchAndParse(self.GetListingURL()) + self.githash_svn_dict.update(new_dict) + last_change_rev = None + + # If the result list was truncated, refetch with the next marker. Do this + # until an entire directory listing is done. + while next_marker: + sys.stdout.write('\rFetching revisions at marker %s' % next_marker) + sys.stdout.flush() + + next_url = self.GetListingURL(next_marker) + (new_revisions, next_marker, new_dict) = _FetchAndParse(next_url) + revisions.extend(new_revisions) + self.githash_svn_dict.update(new_dict) + if last_change_rev and last_change_rev in new_revisions: + break + sys.stdout.write('\r') + sys.stdout.flush() + return revisions + + def _GetSVNRevisionFromGitHashWithoutGitCheckout(self, git_sha1, depot): + json_url = GITHASH_TO_SVN_URL[depot] % git_sha1 + response = urllib.request.urlopen(json_url) + if response.getcode() == 200: + try: + data = json.loads(response.read()[4:]) + except ValueError: + print('ValueError for JSON URL: %s' % json_url) + raise ValueError + else: + raise ValueError + if 'message' in data: + message = data['message'].split('\n') + message = [line for line in message if line.strip()] + search_pattern = re.compile(SEARCH_PATTERN[depot]) + result = search_pattern.search(message[len(message)-1]) + if result: + return result.group(1) + else: + if depot == 'chromium': + result = re.search(CHROMIUM_SEARCH_PATTERN_OLD, + message[len(message)-1]) + if result: + return result.group(1) + print('Failed to get svn revision number for %s' % git_sha1) + raise ValueError + + def _GetSVNRevisionFromGitHashFromGitCheckout(self, git_sha1, depot): + def _RunGit(command, path): + command = ['git'] + command + shell = sys.platform.startswith('win') + proc = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, cwd=path) + (output, _) = proc.communicate() + return (output, proc.returncode) + + path = self.local_src_path + if depot == 'blink': + path = os.path.join(self.local_src_path, 'third_party', 'WebKit') + revision = None + try: + command = ['svn', 'find-rev', git_sha1] + (git_output, return_code) = _RunGit(command, path) + if not return_code: + revision = git_output.strip('\n') + except ValueError: + pass + if not revision: + command = ['log', '-n1', '--format=%s', git_sha1] + (git_output, return_code) = _RunGit(command, path) + if not return_code: + revision = re.match('SVN changes up to revision ([0-9]+)', git_output) + revision = revision.group(1) if revision else None + if revision: + return revision + raise ValueError + + def GetSVNRevisionFromGitHash(self, git_sha1, depot='chromium'): + if not self.local_src_path: + return self._GetSVNRevisionFromGitHashWithoutGitCheckout(git_sha1, depot) + else: + return self._GetSVNRevisionFromGitHashFromGitCheckout(git_sha1, depot) + + def GetRevList(self): + """Gets the list of revision numbers between self.good_revision and + self.bad_revision.""" + + cache = {} + # The cache is stored in the same directory as bisect-builds.py + cache_filename = os.path.join( + os.path.abspath(os.path.dirname(__file__)), + '.bisect-builds-cache.json') + cache_dict_key = self.GetListingURL() + + def _LoadBucketFromCache(): + if self.use_local_cache: + try: + with open(cache_filename) as cache_file: + for (key, value) in list(json.load(cache_file).items()): + cache[key] = value + revisions = cache.get(cache_dict_key, []) + githash_svn_dict = cache.get('githash_svn_dict', {}) + if revisions: + print('Loaded revisions %d-%d from %s' % (revisions[0], + revisions[-1], cache_filename)) + return (revisions, githash_svn_dict) + except (EnvironmentError, ValueError): + pass + return ([], {}) + + def _SaveBucketToCache(): + """Save the list of revisions and the git-svn mappings to a file. + The list of revisions is assumed to be sorted.""" + if self.use_local_cache: + cache[cache_dict_key] = revlist_all + cache['githash_svn_dict'] = self.githash_svn_dict + try: + with open(cache_filename, 'w') as cache_file: + json.dump(cache, cache_file) + print('Saved revisions %d-%d to %s' % ( + revlist_all[0], revlist_all[-1], cache_filename)) + except EnvironmentError: + pass + + # Download the revlist and filter for just the range between good and bad. + minrev = min(self.good_revision, self.bad_revision) + maxrev = max(self.good_revision, self.bad_revision) + + (revlist_all, self.githash_svn_dict) = _LoadBucketFromCache() + last_known_rev = revlist_all[-1] if revlist_all else 0 + if last_known_rev < maxrev: + if self.is_official: + revlist_all.extend(list(map(int, self.GetPerCLRevList()))) + else: + revlist_all.extend(list(map(int, self.ParseDirectoryIndex(last_known_rev)))) + revlist_all = list(set(revlist_all)) + revlist_all.sort() + _SaveBucketToCache() + + revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)] + + # Set good and bad revisions to be legit revisions. + if revlist: + if self.good_revision < self.bad_revision: + self.good_revision = revlist[0] + self.bad_revision = revlist[-1] + else: + self.bad_revision = revlist[0] + self.good_revision = revlist[-1] + + # Fix chromium rev so that the deps blink revision matches REVISIONS file. + if self.base_url == WEBKIT_BASE_URL: + revlist_all.sort() + self.good_revision = FixChromiumRevForBlink(revlist, + revlist_all, + self, + self.good_revision) + self.bad_revision = FixChromiumRevForBlink(revlist, + revlist_all, + self, + self.bad_revision) + return revlist + + def GsutilExists(self, query): + output = RunGsutilCommand(['stat', query], can_fail=True) + if output.startswith(query): + return True + elif 'No URLs matched' in output: + return False + else: + raise Exception('Error running the gsutil command: %s' % output) + + def GsutilList(self, query): + # Get a directory listing with file sizes. Typical output looks like: + # 7 2023-11-27T21:08:36Z gs://.../LAST_CHANGE + # 144486938 2023-03-07T14:41:25Z gs://.../full-build-win32_1113893.zip + # TOTAL: 114167 objects, 15913845813421 bytes (14.47 TiB) + # This lets us ignore empty .zip files that will otherwise cause errors. + stdout = RunGsutilCommand(['ls', '-l', query]) + # Trim off the summary line that only happens with -l + temp = stdout.splitlines()[:-1] + lines = [] + for line in temp: + parts = line.split() + # Check whether there is a size field. For release builds the listing + # will be directories so there will be no size field. + if len(parts) > 1: + size = int(parts[0]) + # Empty .zip files are 22 bytes. Ignore anything less than 1,000 bytes, + # but keep the LAST_CHANGE file since the code seems to expect that. + if parts[-1].endswith('LAST_CHANGE') or size > 1000: + lines.append(parts[-1]) + else: + lines.append(parts[-1]) + results = [url[len(query):].strip('/') for url in lines] + return results + + def GetPerCLRevList(self): + """ Gets the list of revision numbers between self.good_revision and + self.bad_revision from a perf build.""" + minrev = min(self.good_revision, self.bad_revision) + maxrev = max(self.good_revision, self.bad_revision) + perf_bucket = '%s/%s' % (PERF_BASE_URL, self._listing_platform_dir) + revision_re = re.compile(r'%s_(\d+)\.zip' %(self._archive_extract_dir)) + revision_files = self.GsutilList(perf_bucket) + revision_numbers = [] + + for revision_file in revision_files: + revision_num = re.match(revision_re, revision_file) + if revision_num: + revision_numbers.append(int(revision_num.groups()[0])) + final_list = [] + for revision_number in sorted(revision_numbers): + if revision_number > maxrev: + break + if revision_number < minrev: + continue + final_list.append(revision_number) + return final_list + + def GetPerfCLRevListFromBackup(self): + """Checks for builds in older GS folders.""" + revlist = [] + # Lacros doesn't have the old backup builds. + if 'lacros' in self.platform: + return revlist + for f in OFFICIAL_BACKUP_BUILDS[self.platform]['listing_platform_dir']: + print('Checking "%s" directory for build archives...' % f) + self._listing_platform_dir = f + revlist = self.GetPerCLRevList() + if len(revlist) >= 2: + break + + return revlist + + def GetReleaseBuildsList(self): + """Gets the list of release build numbers between self.good_revision and + self.bad_revision.""" + # Download the revlist and filter for just the range between good and bad. + minrev = min(self.good_revision, self.bad_revision) + maxrev = max(self.good_revision, self.bad_revision) + # Check against a version number that is many years in the future in order + # to detect when a revision number is passed instead of a version number. + if maxrev > LooseVersion('2000'): + raise BisectException('Max version of %s is too high. Be sure to use a ' + 'version number, not revision number with release ' + 'builds.' % maxrev) + build_numbers = self.GsutilList(RELEASE_BASE_URL) + revision_re = re.compile(r'(\d+\.\d\.\d{4}\.\d+)') + build_numbers = [b for b in build_numbers if revision_re.search(b)] + final_list = [] + parsed_build_numbers = [LooseVersion(x) for x in build_numbers] + parsed_build_numbers = sorted(parsed_build_numbers) + start = bisect.bisect_left(parsed_build_numbers, minrev) + end = bisect.bisect_right(parsed_build_numbers, maxrev) + # Each call to GsutilExists takes about one second so give an estimate of + # the wait time. + build_count = end - start + print('Checking the existence of %d builds. This will take about %.1f ' + 'minutes' % (build_count, build_count / 60.0)) + for build_number in parsed_build_numbers[start:end]: + path = (RELEASE_BASE_URL + '/' + str(build_number) + '/' + + self._listing_platform_dir + self.archive_name) + if self.GsutilExists(path): + final_list.append(str(build_number)) + print('Found %d builds' % len(final_list)) + return final_list + + +def IsMac(): + return sys.platform.startswith('darwin') + + +def UnzipFilenameToDir(filename, directory): + """Unzip |filename| to |directory|.""" + cwd = os.getcwd() + if not os.path.isabs(filename): + filename = os.path.join(cwd, filename) + # Make base. + if not os.path.isdir(directory): + os.mkdir(directory) + os.chdir(directory) + + # The Python ZipFile does not support symbolic links, which makes it + # unsuitable for Mac builds. so use ditto instead. + if IsMac(): + unzip_cmd = ['ditto', '-x', '-k', filename, '.'] + proc = subprocess.Popen(unzip_cmd, bufsize=0, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc.communicate() + os.chdir(cwd) + return + + zf = zipfile.ZipFile(filename) + # Extract files. + for info in zf.infolist(): + name = info.filename + if name.endswith('/'): # dir + if not os.path.isdir(name): + os.makedirs(name) + else: # file + directory = os.path.dirname(name) + if directory and not os.path.isdir(directory): + os.makedirs(directory) + out = open(name, 'wb') + out.write(zf.read(name)) + out.close() + # Set permissions. Permission info in external_attr is shifted 16 bits. + os.chmod(name, info.external_attr >> 16) + os.chdir(cwd) + + +def gsutil_download(download_url, filename): + command = ['cp', download_url, filename] + RunGsutilCommand(command) + + +def FetchRevision(context, rev, filename, quit_event=None, progress_event=None): + """Downloads and unzips revision |rev|. + @param context A PathContext instance. + @param rev The Chromium revision number/tag to download. + @param filename The destination for the downloaded file. + @param quit_event A threading.Event which will be set by the master thread to # nocheck + indicate that the download should be aborted. + @param progress_event A threading.Event which will be set by the master thread # nocheck + to indicate that the progress of the download should be + displayed. + """ + def ReportHook(blocknum, blocksize, totalsize): + if quit_event and quit_event.isSet(): + raise RuntimeError('Aborting download of revision %s' % str(rev)) + if progress_event and progress_event.isSet(): + size = blocknum * blocksize + if totalsize == -1: # Total size not known. + progress = 'Received %d bytes' % size + else: + size = min(totalsize, size) + progress = 'Received %d of %d bytes, %.2f%%' % ( + size, totalsize, 100.0 * size / totalsize) + # Send a \r to let all progress messages use just one line of output. + sys.stdout.write('\r' + progress) + sys.stdout.flush() + download_url = context.GetDownloadURL(rev) + try: + if download_url.startswith('gs'): + gsutil_download(download_url, filename) + else: + urllib.request.urlretrieve(download_url, filename, ReportHook) + if progress_event and progress_event.isSet(): + print() + except RuntimeError: + pass + + +def RunRevisionForAndroid(context, revision, zip_file): + """Installs apk and launches chrome for android bisect.""" + try: + tempdir = tempfile.mkdtemp(prefix='bisect_tmp') + UnzipFilenameToDir(zip_file, tempdir) + apk_path = os.path.join(tempdir, CHROME_APK_FILENAMES[context.apk]) + InstallonAndroid(context.device, apk_path) + LaunchOnAndroid(context.device, context.apk) + finally: + try: + shutil.rmtree(tempdir, True) + except Exception: + pass + return (0, sys.stdout, sys.stderr) + + +def InstallRevisionForLacros(context, zip_file): + """Install revision on cros device.""" + + try: + tempdir = tempfile.mkdtemp(prefix='bisect_tmp') + UnzipFilenameToDir(zip_file, tempdir) + if context.is_official: + tempdir = os.path.join(tempdir, context._archive_extract_dir) + + cmdline = [context.deploy_chrome_path, '--build-dir=' + tempdir, + '--device=' + context.device, '--nostrip', '--lacros', '--reset-lacros'] + print('Lacros deploy command:\n') + print(' '.join(cmdline)) + subproc = subprocess.Popen(cmdline) + (stdout, stderr) = subproc.communicate() + if subproc.returncode == 0: + print('deploy succeeded!') + print('You may now click Lacros icon on DUT to start testing.') + else: + print('deploy failed!') + return (subproc.returncode, stdout, stderr) + finally: + try: + shutil.rmtree(tempdir, True) + except Exception: + pass + + +def RunRevision( + context, revision, zip_file, profile, num_runs, command, args): + """Given a zipped revision, unzip it and run the test.""" + print('Trying revision %s...' % str(revision)) + if context.platform in ['arm', 'arm64']: + return RunRevisionForAndroid(context, revision, zip_file) + + if context.platform in ['lacros64', 'lacros-arm32', 'lacros-arm64']: + return InstallRevisionForLacros(context, zip_file) + + # Create a temp directory and unzip the revision into it. + cwd = os.getcwd() + tempdir = tempfile.mkdtemp(prefix='bisect_tmp') + # On Windows 10, file system needs to be readable from App Container. + if sys.platform == 'win32' and platform.release() == '10': + icacls_cmd = ['icacls', tempdir, '/grant', '*S-1-15-2-2:(OI)(CI)(RX)'] + proc = subprocess.Popen(icacls_cmd, + bufsize=0, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + proc.communicate() + + UnzipFilenameToDir(zip_file, tempdir) + + # Special case for perf builds. The directory can be either versioned + # or unversioned. For example, full-build-linux directory will be converted to + # full-build-linux_<revision_number> directoy. + if context.is_official: + unversioned_archive = os.path.join(tempdir, context._archive_extract_dir) + if os.path.isdir(unversioned_archive): + versioned_archive = os.path.join( + tempdir, '%s_%s'% (context._archive_extract_dir, revision)) + # On Windows this renaming can transiently fail - because of + # antivirus software, even in monitoring mode? - so retry it up + # to a few times. It seems it can fail for at least 10 seconds + # in a row on developers' machines. + retries = 20 + succeeded = False + while not succeeded: + try: + os.rename(unversioned_archive, versioned_archive) + succeeded = True + except Exception as e: + retries -= 1 + if retries == 0: + print('Failed to rename: ' + unversioned_archive) + print(' to: ' + versioned_archive) + raise e + time.sleep(1) + # Hack: Chrome OS archives are missing icudtl.dat; try to copy it from + # the local directory. + if context.platform == 'chromeos' and revision < 591483: + icudtl_path = 'third_party/icu/common/icudtl.dat' + if not os.access(icudtl_path, os.F_OK): + print('Couldn\'t find: ' + icudtl_path) + sys.exit() + os.system('cp %s %s/chrome-linux/' % (icudtl_path, tempdir)) + + os.chdir(tempdir) + + # Run the build as many times as specified. + testargs = ['--user-data-dir=%s' % profile] + args + # The sandbox must be run as root on release Chrome, so bypass it. + if ((context.is_release or context.flash_path) and + context.platform.startswith('linux')): + testargs.append('--no-sandbox') + if context.flash_path: + testargs.append('--ppapi-flash-path=%s' % context.flash_path) + # We have to pass a large enough Flash version, which currently needs not + # be correct. Instead of requiring the user of the script to figure out and + # pass the correct version we just spoof it. + testargs.append('--ppapi-flash-version=99.9.999.999') + + runcommand = [] + for token in shlex.split(command): + if token == '%a': + runcommand.extend(testargs) + else: + runcommand.append( + token.replace('%p', os.path.abspath(context.GetLaunchPath(revision))). + replace('%s', ' '.join(testargs))) + + results = [] + if is_verbose: + print(('Running ' + str(runcommand))) + for _ in range(num_runs): + subproc = subprocess.Popen(runcommand, + bufsize=-1, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (stdout, stderr) = subproc.communicate() + results.append((subproc.returncode, stdout, stderr)) + os.chdir(cwd) + try: + shutil.rmtree(tempdir, True) + except Exception: + pass + + for (returncode, stdout, stderr) in results: + if returncode: + return (returncode, stdout, stderr) + return results[0] + + +# The arguments release_builds, status, stdout and stderr are unused. +# They are present here because this function is passed to Bisect which then +# calls it with 5 arguments. +# pylint: disable=W0613 +def AskIsGoodBuild(rev, release_builds, exit_status, stdout, stderr): + """Asks the user whether build |rev| is good or bad.""" + # Loop until we get a response that we can parse. + while True: + response = input('Revision %s is ' + '[(g)ood/(b)ad/(r)etry/(u)nknown/(s)tdout/(q)uit]: ' % + str(rev)) + if response in ('g', 'b', 'r', 'u'): + return response + if response == 'q': + raise SystemExit() + if response == 's': + print(stdout) + print(stderr) + + +def IsGoodASANBuild(rev, release_builds, exit_status, stdout, stderr): + """Determine if an ASAN build |rev| is good or bad + + Will examine stderr looking for the error message emitted by ASAN. If not + found then will fallback to asking the user.""" + if stderr: + bad_count = 0 + for line in stderr.splitlines(): + print(line) + if line.find('ERROR: AddressSanitizer:') != -1: + bad_count += 1 + if bad_count > 0: + print('Revision %d determined to be bad.' % rev) + return 'b' + return AskIsGoodBuild(rev, release_builds, exit_status, stdout, stderr) + + +def DidCommandSucceed(rev, release_builds, exit_status, stdout, stderr): + if exit_status: + print('Bad revision: %s' % rev) + return 'b' + else: + print('Good revision: %s' % rev) + return 'g' + + +class DownloadJob(object): + """DownloadJob represents a task to download a given Chromium revision.""" + + def __init__(self, context, name, rev, zip_file): + super(DownloadJob, self).__init__() + # Store off the input parameters. + self.context = context + self.name = name + self.rev = rev + self.zip_file = zip_file + self.quit_event = threading.Event() + self.progress_event = threading.Event() + self.thread = None + + def Start(self): + """Starts the download.""" + fetchargs = (self.context, + self.rev, + self.zip_file, + self.quit_event, + self.progress_event) + self.thread = threading.Thread(target=FetchRevision, + name=self.name, + args=fetchargs) + self.thread.start() + + def Stop(self): + """Stops the download which must have been started previously.""" + assert self.thread, 'DownloadJob must be started before Stop is called.' + self.quit_event.set() + self.thread.join() + try: + os.unlink(self.zip_file) + except FileNotFoundError: + # Handle missing archives. + pass + + def WaitFor(self): + """Prints a message and waits for the download to complete. The download + must have been started previously.""" + assert self.thread, 'DownloadJob must be started before WaitFor is called.' + print('Downloading revision %s...' % str(self.rev)) + self.progress_event.set() # Display progress of download. + try: + while self.thread.is_alive(): + # The parameter to join is needed to keep the main thread responsive to + # signals. Without it, the program will not respond to interruptions. + self.thread.join(1) + except (KeyboardInterrupt, SystemExit): + self.Stop() + raise + + +def VerifyEndpoint(fetch, context, rev, profile, num_runs, command, try_args, + evaluate, expected_answer): + fetch.WaitFor() + try: + (exit_status, stdout, stderr) = RunRevision( + context, rev, fetch.zip_file, profile, num_runs, command, try_args) + except Exception as e: + if not isinstance(e, SystemExit): + traceback.print_exc(file=sys.stderr) + exit_status = None + stdout = None + stderr = None + if (evaluate(rev, context.is_release, exit_status, stdout, stderr) != + expected_answer): + print('Unexpected result at a range boundary! Your range is not correct.') + raise SystemExit + + +def Bisect(context, + num_runs=1, + command='%p %a', + try_args=(), + profile='profile', + evaluate=AskIsGoodBuild, + verify_range=False): + """Runs a binary search on to determine the last known good revision. + + Args: + context: PathContext object initialized with user provided parameters. + num_runs: Number of times to run each build for asking good/bad. + try_args: A tuple of arguments to pass to the test application. + profile: The name of the user profile to run with. + evaluate: A function which returns 'g' if the argument build is good, + 'b' if it's bad or 'u' if unknown. + verify_range: If true, tests the first and last revisions in the range + before proceeding with the bisect. + + Threading is used to fetch Chromium revisions in the background, speeding up + the user's experience. For example, suppose the bounds of the search are + good_rev=0, bad_rev=100. The first revision to be checked is 50. Depending on + whether revision 50 is good or bad, the next revision to check will be either + 25 or 75. So, while revision 50 is being checked, the script will download + revisions 25 and 75 in the background. Once the good/bad verdict on rev 50 is + known: + - If rev 50 is good, the download of rev 25 is cancelled, and the next test + is run on rev 75. + - If rev 50 is bad, the download of rev 75 is cancelled, and the next test + is run on rev 25. + """ + good_rev = context.good_revision + bad_rev = context.bad_revision + cwd = os.getcwd() + + print('Downloading list of known revisions.', end=' ') + print('If the range is large, this can take several minutes...') + if not context.use_local_cache and not context.is_release: + print('(use --use-local-cache to cache and re-use the list of revisions)') + else: + print() + _GetDownloadPath = lambda rev: os.path.join(cwd, + '%s-%s' % (str(rev), context.archive_name)) + if context.is_release: + revlist = context.GetReleaseBuildsList() + elif context.is_official: + revlist = context.GetRevList() + + # https://crbug.com/837719, https://crbug.com/893686 + # Whenever there is change in Perf builder names (responsible for producing + # chrome builds for functional bisects), the storage location for the + # builds changes. Due to this the script fails to find the build archives + # for older revisions in new location. + # OFFICIAL_BACKUP_BUILDS define all such old builds location per platform, + # and fallback to search in these folders if build archives are not found in + # new location. + if len(revlist) < 2: + print(('Couldn\'t find enough builds in %s folder, ' + 'checking in other directories...' % context._listing_platform_dir)) + revlist = context.GetPerfCLRevListFromBackup() + build_range = abs(context.bad_revision - context.good_revision) + 1 + build_percent = (float(len(revlist))* 100) / build_range + print(('Total of %d percent of perf builds available in the range' + % build_percent)) + else: + revlist = context.GetRevList() + + # Get a list of revisions to bisect across. + if len(revlist) < 2: # Don't have enough builds to bisect. + msg = 'We don\'t have enough builds to bisect. revlist: %s' % revlist + raise RuntimeError(msg) + + # Figure out our bookends and first pivot point; fetch the pivot revision. + minrev = 0 + maxrev = len(revlist) - 1 + pivot = maxrev // 2 + rev = revlist[pivot] + fetch = DownloadJob(context, 'initial_fetch', rev, _GetDownloadPath(rev)) + fetch.Start() + + if verify_range: + minrev_fetch = DownloadJob( + context, 'minrev_fetch', revlist[minrev], + _GetDownloadPath(revlist[minrev])) + maxrev_fetch = DownloadJob( + context, 'maxrev_fetch', revlist[maxrev], + _GetDownloadPath(revlist[maxrev])) + minrev_fetch.Start() + maxrev_fetch.Start() + try: + VerifyEndpoint(minrev_fetch, context, revlist[minrev], profile, num_runs, + command, try_args, evaluate, 'b' if bad_rev < good_rev else 'g') + VerifyEndpoint(maxrev_fetch, context, revlist[maxrev], profile, num_runs, + command, try_args, evaluate, 'g' if bad_rev < good_rev else 'b') + except (KeyboardInterrupt, SystemExit): + print('Cleaning up...') + fetch.Stop() + sys.exit(0) + finally: + minrev_fetch.Stop() + maxrev_fetch.Stop() + + fetch.WaitFor() + + # Binary search time! + while fetch and fetch.zip_file and maxrev - minrev > 1: + if bad_rev < good_rev: + min_str, max_str = 'bad', 'good' + else: + min_str, max_str = 'good', 'bad' + print('Bisecting range [%s (%s), %s (%s)].' % (revlist[minrev], min_str, + revlist[maxrev], max_str)) + + # Pre-fetch next two possible pivots + # - down_pivot is the next revision to check if the current revision turns + # out to be bad. + # - up_pivot is the next revision to check if the current revision turns + # out to be good. + down_pivot = int((pivot - minrev) / 2) + minrev + down_fetch = None + if down_pivot != pivot and down_pivot != minrev: + down_rev = revlist[down_pivot] + down_fetch = DownloadJob(context, 'down_fetch', down_rev, + _GetDownloadPath(down_rev)) + down_fetch.Start() + + up_pivot = int((maxrev - pivot) / 2) + pivot + up_fetch = None + if up_pivot != pivot and up_pivot != maxrev: + up_rev = revlist[up_pivot] + up_fetch = DownloadJob(context, 'up_fetch', up_rev, + _GetDownloadPath(up_rev)) + up_fetch.Start() + + # Run test on the pivot revision. + exit_status = None + stdout = None + stderr = None + try: + (exit_status, stdout, stderr) = RunRevision( + context, rev, fetch.zip_file, profile, num_runs, command, try_args) + except SystemExit: + raise + except Exception: + traceback.print_exc(file=sys.stderr) + + # Call the evaluate function to see if the current revision is good or bad. + # On that basis, kill one of the background downloads and complete the + # other, as described in the comments above. + try: + answer = evaluate(rev, context.is_release, exit_status, stdout, stderr) + if ((answer == 'g' and good_rev < bad_rev) + or (answer == 'b' and bad_rev < good_rev)): + fetch.Stop() + minrev = pivot + if down_fetch: + down_fetch.Stop() # Kill the download of the older revision. + fetch = None + if up_fetch: + up_fetch.WaitFor() + pivot = up_pivot + fetch = up_fetch + elif ((answer == 'b' and good_rev < bad_rev) + or (answer == 'g' and bad_rev < good_rev)): + fetch.Stop() + maxrev = pivot + if up_fetch: + up_fetch.Stop() # Kill the download of the newer revision. + fetch = None + if down_fetch: + down_fetch.WaitFor() + pivot = down_pivot + fetch = down_fetch + elif answer == 'r': + pass # Retry requires no changes. + elif answer == 'u': + # Nuke the revision from the revlist and choose a new pivot. + fetch.Stop() + revlist.pop(pivot) + maxrev -= 1 # Assumes maxrev >= pivot. + + if maxrev - minrev > 1: + # Alternate between using down_pivot or up_pivot for the new pivot + # point, without affecting the range. Do this instead of setting the + # pivot to the midpoint of the new range because adjacent revisions + # are likely affected by the same issue that caused the (u)nknown + # response. + if up_fetch and down_fetch: + fetch = [up_fetch, down_fetch][len(revlist) % 2] + elif up_fetch: + fetch = up_fetch + else: + fetch = down_fetch + fetch.WaitFor() + if fetch == up_fetch: + pivot = up_pivot - 1 # Subtracts 1 because revlist was resized. + else: + pivot = down_pivot + + if down_fetch and fetch != down_fetch: + down_fetch.Stop() + if up_fetch and fetch != up_fetch: + up_fetch.Stop() + else: + assert False, 'Unexpected return value from evaluate(): ' + answer + except (KeyboardInterrupt, SystemExit): + print('Cleaning up...') + for f in [_GetDownloadPath(rev), + _GetDownloadPath(revlist[down_pivot]), + _GetDownloadPath(revlist[up_pivot])]: + try: + os.unlink(f) + except OSError: + pass + sys.exit(0) + + rev = revlist[pivot] + + return (revlist[minrev], revlist[maxrev], context) + + +def GetBlinkDEPSRevisionForChromiumRevision(self, rev): + """Returns the blink revision that was in REVISIONS file at + chromium revision |rev|.""" + + def _GetBlinkRev(url, blink_re): + m = blink_re.search(url.read()) + url.close() + if m: + return m.group(1) + + url = urllib.request.urlopen(DEPS_FILE_OLD % rev) + if url.getcode() == 200: + # . doesn't match newlines without re.DOTALL, so this is safe. + blink_re = re.compile(r'webkit_revision\D*(\d+)') + return int(_GetBlinkRev(url, blink_re)) + else: + url = urllib.request.urlopen(DEPS_FILE_NEW % GetGitHashFromSVNRevision(rev)) + if url.getcode() == 200: + blink_re = re.compile(r'webkit_revision\D*\d+;\D*\d+;(\w+)') + blink_git_sha = _GetBlinkRev(url, blink_re) + return self.GetSVNRevisionFromGitHash(blink_git_sha, 'blink') + raise Exception('Could not get Blink revision for Chromium rev %d' % rev) + + +def GetBlinkRevisionForChromiumRevision(context, rev): + """Returns the blink revision that was in REVISIONS file at + chromium revision |rev|.""" + def _IsRevisionNumber(revision): + if isinstance(revision, int): + return True + else: + return revision.isdigit() + if str(rev) in context.githash_svn_dict: + rev = context.githash_svn_dict[str(rev)] + file_url = '%s/%s%s/REVISIONS' % (context.base_url, + context._listing_platform_dir, rev) + url = urllib.request.urlopen(file_url) + if url.getcode() == 200: + try: + data = json.loads(url.read()) + except ValueError: + print('ValueError for JSON URL: %s' % file_url) + raise ValueError + else: + raise ValueError + url.close() + if 'webkit_revision' in data: + blink_rev = data['webkit_revision'] + if not _IsRevisionNumber(blink_rev): + blink_rev = int(context.GetSVNRevisionFromGitHash(blink_rev, 'blink')) + return blink_rev + else: + raise Exception('Could not get blink revision for cr rev %d' % rev) + + +def FixChromiumRevForBlink(revisions_final, revisions, self, rev): + """Returns the chromium revision that has the correct blink revision + for blink bisect, DEPS and REVISIONS file might not match since + blink snapshots point to tip of tree blink. + Note: The revisions_final variable might get modified to include + additional revisions.""" + blink_deps_rev = GetBlinkDEPSRevisionForChromiumRevision(self, rev) + + while (GetBlinkRevisionForChromiumRevision(self, rev) > blink_deps_rev): + idx = revisions.index(rev) + if idx > 0: + rev = revisions[idx-1] + if rev not in revisions_final: + revisions_final.insert(0, rev) + + revisions_final.sort() + return rev + + +def GetChromiumRevision(context, url): + """Returns the chromium revision read from given URL.""" + try: + # Location of the latest build revision number + latest_revision = urllib.request.urlopen(url).read() + if latest_revision.isdigit(): + return int(latest_revision) + return context.GetSVNRevisionFromGitHash(latest_revision) + except Exception: + print('Could not determine latest revision. This could be bad...') + return 999999999 + +def FetchJsonFromURL(url): + """Returns JSON data from the given URL""" + url = urllib.request.urlopen(url) + # Allow retry for 3 times for unexpected network error + for i in range(3): + if url.getcode() == 200: + data = json.loads(url.read()) + return data + return None + +def GetGitHashFromSVNRevision(svn_revision): + """Returns GitHash from SVN Revision""" + crrev_url = CRREV_URL + str(svn_revision) + data = FetchJsonFromURL(crrev_url) + if data and 'git_sha' in data: + return data['git_sha'] + return None + +def PrintChangeLog(min_chromium_rev, max_chromium_rev): + """Prints the changelog URL.""" + print((' ' + CHANGELOG_URL % (GetGitHashFromSVNRevision(min_chromium_rev), + GetGitHashFromSVNRevision(max_chromium_rev)))) + +def IsVersionNumber(revision): + """Checks if provided revision is version_number""" + return re.match(r'^\d+\.\d+\.\d+\.\d+$', revision) is not None + + +def GetRevisionFromVersion(version): + """Returns Base Commit Position from a version number""" + chromiumdash_url = VERSION_INFO_URL % str(version) + data = FetchJsonFromURL(chromiumdash_url) + if data and 'chromium_main_branch_position' in data: + return data['chromium_main_branch_position'] + print('Something went wrong. The data we got from chromiumdash:\n%s' % data) + return None + +def CheckDepotToolsInPath(): + delimiter = ';' if sys.platform.startswith('win') else ':' + path_list = os.environ['PATH'].split(delimiter) + for path in path_list: + if path.rstrip(os.path.sep).endswith('depot_tools'): + return path + return None + +def SetupEnvironment(options): + global is_verbose + + # Release and Official builds bisect requires "gsutil" inorder to + # List and Download binaries. + # Check if depot_tools is installed and path is set. + gsutil_path = CheckDepotToolsInPath() + if ((options.release_builds or options.official_builds) and + not gsutil_path): + raise BisectException('Looks like depot_tools is not installed.\n' + 'Follow the instructions in this document ' + 'http://dev.chromium.org/developers/how-tos/install-depot-tools ' + 'to install depot_tools and then try again.') + + global GSUTILS_PATH + GSUTILS_PATH = os.path.join(gsutil_path, 'gsutil.py') + + # Catapult repo is required for Android bisect, + # Update Catapult repo if it exists otherwise checkout repo. + if options.archive in ['arm', 'arm64']: + SetupAndroidEnvironment() + + # Set up verbose logging if requested. + if options.verbose: + is_verbose = True + +def SetupAndroidEnvironment(): + def SetupCatapult(): + print('Setting up Catapult in %s.' % CATAPULT_DIR) + print('Set the environment var CATAPULT_DIR to override Catapult directory.') + if (os.path.exists(CATAPULT_DIR)): + print('Updating Catapult...\n') + process = subprocess.Popen( + args=['git', 'pull', '--rebase'], + cwd=CATAPULT_DIR) + exit_code = process.wait() + if exit_code != 0: + raise BisectException('Android bisect requires Catapult repo checkout. ' + 'Attempt to update Catapult failed.') + else: + print('Downloading Catapult...\n') + process = subprocess.Popen( + args=['git', 'clone', CATAPULT_REPO, CATAPULT_DIR]) + exit_code = process.wait() + if exit_code != 0: + raise BisectException('Android bisect requires Catapult repo checkout. ' + 'Attempt to download Catapult failed.') + SetupCatapult() + sys.path.append(DEVIL_PATH) + # Modules required from devil + devil_imports = { + 'devil_env': 'devil.devil_env', + 'device_errors': 'devil.android.device_errors', + 'device_utils': 'devil.android.device_utils', + 'flag_changer': 'devil.android.flag_changer', + 'chrome': 'devil.android.constants.chrome', + 'adb_wrapper': 'devil.android.sdk.adb_wrapper', + 'intent': 'devil.android.sdk.intent', + 'version_codes': 'devil.android.sdk.version_codes', + 'run_tests_helper': 'devil.utils.run_tests_helper' + } + # Dynamically import devil modules required for android bisect. + for i, j in devil_imports.items(): + globals()[i] = importlib.import_module(j) + + print('Done setting up Catapult.\n') + + +def InitializeAndroidDevice(device_id, apk, chrome_flags): + """Initializes device and sets chrome flags.""" + devil_env.config.Initialize() + run_tests_helper.SetLogLevel(0) + device = device_utils.DeviceUtils.HealthyDevices(device_arg=device_id)[0] + if chrome_flags: + flags = flag_changer.FlagChanger(device, + chrome.PACKAGE_INFO[apk].cmdline_file) + flags.AddFlags(chrome_flags) + return device + + +def InstallonAndroid(device, apk_path ): + """Installs the chromium build on a given device.""" + print('Installing %s on android device...' % apk_path) + device.Install(apk_path) + + +def LaunchOnAndroid(device, apk): + """Launches the chromium build on a given device.""" + print('Launching chrome on android device...') + device.StartActivity( + intent.Intent( + action='android.intent.action.MAIN', + activity=chrome.PACKAGE_INFO[apk].activity, + package=chrome.PACKAGE_INFO[apk].package), + blocking=True, + force_stop=True) + + +def _CreateCommandLineParser(): + """Creates a parser with bisect options. + + Returns: + An instance of argparse.ArgumentParser. + """ + usage = """%prog [options] [-- chromium-options] + +Performs binary search on the chrome binaries to find a minimal range of +revisions where a behavior change happened. +The behaviors are described as "good" and "bad". It is NOT assumed that the +behavior of the later revision is the bad one. + +Revision numbers should use: + a) Release versions: (e.g. 1.0.1000.0) for release builds. (-r) + b) Commit Positions: (e.g. 123456) for chromium builds, from trunk. + Use chromium_main_branch_position from + https://chromiumdash.appspot.com/fetch_version?version=<chrome_version> + Please Note: Chrome's about: build number and chromiumdash branch + revision are incorrect, they are from branches. + +Tip: add "-- --no-first-run" to bypass the first run prompts. +""" + + parser = optparse.OptionParser(usage=usage) + # Strangely, the default help output doesn't include the choice list. + choices = ['arm', 'arm64', 'mac', 'mac64', 'mac-arm', 'win', 'win-clang', + 'win64', 'win64-clang', 'linux64', 'linux-arm', 'chromeos', + 'lacros64', 'lacros-arm32', 'lacros-arm64'] + parser.add_option('-a', '--archive', + choices=choices, + help='The buildbot archive to bisect [%s].' % + '|'.join(choices)) + parser.add_option('-r', + action='store_true', + dest='release_builds', + help='Bisect across release Chrome builds (internal ' + 'only) instead of Chromium archives.') + parser.add_option('-o', + action='store_true', + dest='official_builds', + help='Bisect across continuous perf officialChrome builds ' + '(internal only) instead of Chromium archives. ' + 'With this flag, you can provide either commit ' + 'position numbers (for example, 397000) or ' + 'version numbers (for example, 53.0.2754.0 ' + 'as good and bad revisions.') + parser.add_option('-b', '--bad', + type='str', + help='A bad revision to start bisection. ' + 'May be earlier or later than the good revision. ' + 'Default is HEAD.') + parser.add_option('-f', '--flash_path', + type='str', + help='Absolute path to a recent Adobe Pepper Flash ' + 'binary to be used in this bisection (e.g. ' + 'on Windows C:\...\pepflashplayer.dll and on Linux ' + '/opt/google/chrome/PepperFlash/' + 'libpepflashplayer.so).') + parser.add_option('-g', '--good', + type='str', + help='A good revision to start bisection. ' + + 'May be earlier or later than the bad revision. ' + + 'Default is 0.') + parser.add_option('-p', '--profile', '--user-data-dir', + type='str', + default='profile', + help='Profile to use; this will not reset every run. ' + 'Defaults to a clean profile.') + parser.add_option('-t', '--times', + type='int', + default=1, + help='Number of times to run each build before asking ' + 'if it\'s good or bad. Temporary profiles are reused.') + parser.add_option('-c', '--command', + type='str', + default='%p %a', + help='Command to execute. %p and %a refer to Chrome ' + 'executable and specified extra arguments ' + 'respectively. Use %s to specify all extra arguments ' + 'as one string. Defaults to "%p %a". Note that any ' + 'extra paths specified should be absolute.') + parser.add_option('-l', '--blink', + action='store_true', + help='Use Blink bisect instead of Chromium. ') + parser.add_option('-v', '--verbose', + action='store_true', + help='Log more verbose information.') + parser.add_option('', '--not-interactive', + action='store_true', + default=False, + help='Use command exit code to tell good/bad revision.') + parser.add_option('--asan', + dest='asan', + action='store_true', + default=False, + help='Allow the script to bisect ASAN builds') + parser.add_option('--use-local-cache', + dest='use_local_cache', + action='store_true', + default=False, + help='Use a local file in the current directory to cache ' + 'a list of known revisions to speed up the ' + 'initialization of this script.') + parser.add_option('--verify-range', + dest='verify_range', + action='store_true', + default=False, + help='Test the first and last revisions in the range ' + + 'before proceeding with the bisect.') + parser.add_option('--apk', + choices=list(CHROME_APK_FILENAMES.keys()), + dest='apk', + default='chromium', + help='Apk you want to bisect.') + parser.add_option('-d', '--device-id', + dest='device_id', + type='str', + help='Device to run the bisect on.') + parser.add_option('--deploy-chrome-path', + dest='deploy_chrome_path', + type='str', + help='deploy_chrome binary path.') + + return parser + + +def ParseCommandLine(args=None): + """Parses the command line for bisect options.""" + official_choices = ['arm', 'arm64', 'linux64', 'mac', 'mac-arm', 'win64', + 'lacros64', 'lacros-arm32', 'lacros-arm64'] + parser = _CreateCommandLineParser() + opts, args = parser.parse_args(args) + + if opts.archive is None: + print('Error: Missing required parameter: --archive') + parser.print_help() + sys.exit(1) + + if not opts.official_builds and opts.archive in ['arm', 'arm64']: + raise NotImplementedError( + 'Android bisect is currently supported only on Official builds.') + + if opts.official_builds and opts.archive not in official_choices: + raise BisectException(('Error: Bisecting on official builds are only ' + 'supported on these platforms: [%s].' + % '|'.join(official_choices))) + elif opts.official_builds and opts.archive in official_choices: + print('Bisecting on continuous Chrome builds. If you would like ' + 'to bisect on release builds, try running with -r option ' + 'instead. Previous -o options is currently changed to -r option ' + 'as continous official builds were added for bisect') + if opts.asan: + supported_platforms = ['linux', 'mac', 'win'] + if opts.archive not in supported_platforms: + print(('Error: ASAN bisecting only supported on these platforms: [%s].' % ( + '|'.join(supported_platforms)))) + sys.exit(1) + if opts.release_builds: + raise NotImplementedError( + 'Do not yet support bisecting release ASAN builds.') + + return opts, args + + +def main(): + opts, args = ParseCommandLine() + + try: + SetupEnvironment(opts) + except BisectException as e: + print(e) + sys.exit(1) + + if opts.official_builds: + # Automatically converts version number to commit position number + if IsVersionNumber(opts.good): + opts.good = GetRevisionFromVersion(opts.good) + opts.bad = GetRevisionFromVersion(opts.bad) + + device = None + if opts.archive in ['arm', 'arm64']: + device = InitializeAndroidDevice(opts.device_id, opts.apk, args) + if not device: + raise BisectException('Failed to initialize device.') + + deploy_chrome_path = None + if opts.archive in ['lacros64', 'lacros-arm32', 'lacros-arm64']: + if not opts.device_id: + raise BisectException('Please specify device id for a cros device.') + device = opts.device_id + if not opts.deploy_chrome_path: + raise BisectException('Please specify deploy_chrome path.') + deploy_chrome_path = opts.deploy_chrome_path + # Create the context. Initialize 0 for the revisions as they are set below. + context = PathContext(opts, device) + + context.deploy_chrome_path = deploy_chrome_path + # Pick a starting point, try to get HEAD for this. + if not opts.bad: + context.bad_revision = '999.0.0.0' + context.bad_revision = GetChromiumRevision( + context, context.GetLastChangeURL()) + + # Find out when we were good. + if not opts.good: + context.good_revision = '0.0.0.0' if opts.release_builds else 0 + + if opts.flash_path: + msg = 'Could not find Flash binary at %s' % opts.flash_path + assert os.path.exists(opts.flash_path), msg + + if opts.release_builds: + context.good_revision = LooseVersion(context.good_revision) + context.bad_revision = LooseVersion(context.bad_revision) + else: + context.good_revision = int(context.good_revision) + context.bad_revision = int(context.bad_revision) + + if opts.times < 1: + print(('Number of times to run (%d) must be greater than or equal to 1.' % + opts.times)) + parser.print_help() + return 1 + + if opts.not_interactive: + evaluator = DidCommandSucceed + elif opts.asan: + evaluator = IsGoodASANBuild + else: + evaluator = AskIsGoodBuild + + # Save these revision numbers to compare when showing the changelog URL + # after the bisect. + good_rev = context.good_revision + bad_rev = context.bad_revision + + (min_chromium_rev, max_chromium_rev, context) = Bisect( + context, opts.times, opts.command, args, opts.profile, + evaluator, opts.verify_range) + + # Get corresponding blink revisions. + try: + min_blink_rev = GetBlinkRevisionForChromiumRevision(context, + min_chromium_rev) + max_blink_rev = GetBlinkRevisionForChromiumRevision(context, + max_chromium_rev) + except Exception: + # Silently ignore the failure. + min_blink_rev, max_blink_rev = 0, 0 + + if opts.blink: + # We're done. Let the user know the results in an official manner. + if good_rev > bad_rev: + print(DONE_MESSAGE_GOOD_MAX % (str(min_blink_rev), str(max_blink_rev))) + else: + print(DONE_MESSAGE_GOOD_MIN % (str(min_blink_rev), str(max_blink_rev))) + + print('BLINK CHANGELOG URL:') + print(' ' + BLINK_CHANGELOG_URL % (max_blink_rev, min_blink_rev)) + + else: + # We're done. Let the user know the results in an official manner. + if good_rev > bad_rev: + print(DONE_MESSAGE_GOOD_MAX % (str(min_chromium_rev), + str(max_chromium_rev))) + else: + print(DONE_MESSAGE_GOOD_MIN % (str(min_chromium_rev), + str(max_chromium_rev))) + if min_blink_rev != max_blink_rev: + print ('NOTE: There is a Blink roll in the range, ' + 'you might also want to do a Blink bisect.') + + print('CHANGELOG URL:') + if opts.release_builds: + print(RELEASE_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)) + else: + if opts.official_builds: + print ('The script might not always return single CL as suspect ' + 'as some perf builds might get missing due to failure.') + PrintChangeLog(min_chromium_rev, max_chromium_rev) + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index ad56a7a..ec781b72 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -700,23 +700,6 @@ PackageInArchive(libclang_dir, libclang_dir) MaybeUpload(args.upload, args.bucket, libclang_dir + '.t*z', gcs_platform) - # Zip up Android x64 ASAN runtime support - if sys.platform.startswith('linux'): - x64_android_asan_dir = 'x64_android_asan' + stamp - shutil.rmtree(x64_android_asan_dir, ignore_errors=True) - subdir = os.path.join('lib', 'clang', RELEASE_VERSION, 'lib', 'linux') - dst_dir = os.path.join(x64_android_asan_dir, subdir) - os.makedirs(dst_dir) - shutil.copy( - os.path.join(LLVM_RELEASE_DIR, subdir, - 'libclang_rt.asan-x86_64-android.so'), dst_dir) - shutil.copy( - os.path.join(LLVM_RELEASE_DIR, subdir, - 'libclang_rt.asan_static-x86_64-android.a'), dst_dir) - PackageInArchive(x64_android_asan_dir, x64_android_asan_dir) - MaybeUpload(args.upload, args.bucket, x64_android_asan_dir + '.t*z', - gcs_platform) - if sys.platform == 'win32' and args.upload: binaries = [f for f in want if f.endswith('.exe') or f.endswith('.dll')] assert 'bin/clang-cl.exe' in binaries
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index a791627c..217fdb3 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -18,6 +18,7 @@ assert sys.version_info >= (3, 0), 'This script requires Python 3.' import argparse +import glob import os import platform import shutil @@ -277,7 +278,11 @@ os.remove(OLD_STAMP_FILE) expected_stamp = ','.join([PACKAGE_VERSION] + target_os) - if ReadStampFile(stamp_file) == expected_stamp: + # This file is created by first class GCS deps. If this file exists, + # clear the entire directory and download with this script instead. + if glob.glob(os.path.join(dir, '.*_is_first_class_gcs')): + RmTree(dir) + elif ReadStampFile(stamp_file) == expected_stamp: return 0 # Updating the main clang package nukes the output dir. Any other packages
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index f95ada6..0b402758 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -407,11 +407,11 @@ "includes": [3840], }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/side_panel/read_anything/resources.grd": { - "META": {"sizes": {"includes": [10],}}, + "META": {"sizes": {"includes": [15],}}, "includes": [3860], }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/side_panel/reading_list/resources.grd": { - "META": {"sizes": {"includes": [10],}}, + "META": {"sizes": {"includes": [15],}}, "includes": [3880], }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/side_panel/shared/resources.grd": {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index b02b652..0fd5152 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -42175,8 +42175,6 @@ </action-suffix> <action-suffix separator="_" ordering="suffix"> - <suffix name="3pcdUserBypass" - label="For third party cookie deprecation user bypass feature."/> <suffix name="AdaptiveButtonInTopToolbarCustomization_AddToBookmarks" label="For AdaptiveButtonInTopToolbarCustomization add to bookmarks feature."/>
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md index dfd252c0..1b8792f3 100644 --- a/tools/metrics/histograms/README.md +++ b/tools/metrics/histograms/README.md
@@ -318,9 +318,11 @@ ### Timing Histograms -You can easily emit a time duration (time delta) using UMA_HISTOGRAM_TIMES, -UMA_HISTOGRAM_MEDIUM_TIMES, UMA_HISTOGRAM_LONG_TIMES macros, and their -friends, as well as helpers like SCOPED_UMA_HISTOGRAM_TIMER. Many timing +You can easily emit a time duration (time delta) using base::UmaHistogramTimes, +base::UmaHistogramMediumTimes, base::UmaHistogramLongTimes, and their friends. +For the critical path, UMA_HISTOGRAM_TIMES, UMA_HISTOGRAM_MEDIUM_TIMES, +UMA_HISTOGRAM_LONG_TIMES macros, and their friends, as well as helpers like +SCOPED_UMA_HISTOGRAM_TIMER are also available. Many timing histograms are used for performance monitoring; if this is the case for you, please read [this document about how to structure timing histograms to make them more useful and
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 2d3249c..b272b92 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -17923,8 +17923,6 @@ <int value="-1450657485" label="EnableHardwareMirrorMode:enabled"/> <int value="-1450576851" label="OmniboxUIExperimentVerticalLayout:enabled"/> <int value="-1449928353" label="TabletToolbarReordering:enabled"/> - <int value="-1449728470" - label="LegacyTechReportEnableCookieIssueReports:disabled"/> <int value="-1449590570" label="RestrictGamepadAccess:enabled"/> <int value="-1449358747" label="RemoveStatusBarInWebApps:enabled"/> <int value="-1448511207" label="UseMessagesStagingUrl:disabled"/> @@ -18727,6 +18725,8 @@ <int value="-1098963611" label="ProjectorLocalPlayback:disabled"/> <int value="-1097977406" label="SupervisedUserCommittedInterstitials:enabled"/> + <int value="-1097149297" + label="EnableAutomaticSharedImageManagement:disabled"/> <int value="-1096694296" label="UpcomingFollowFeatures:enabled"/> <int value="-1096595907" label="disable-new-virtual-keyboard-behavior"/> <int value="-1095947169" label="ModalPermissionDialogView:disabled"/> @@ -18982,8 +18982,6 @@ <int value="-985845117" label="Cardboard:enabled"/> <int value="-985445963" label="TabSearchFuzzySearch:disabled"/> <int value="-984052166" label="DoodlesOnLocalNtp:enabled"/> - <int value="-983747413" - label="EnableFingerprintingProtectionBlockList:enabled"/> <int value="-983342281" label="TabSwitcherLongpressMenu:disabled"/> <int value="-983335806" label="DelegatedCompositing:disabled"/> <int value="-983087919" @@ -19069,6 +19067,7 @@ <int value="-950384924" label="OmniboxDisableInstantExtendedLimit:enabled"/> <int value="-950125294" label="KeyboardAndPointerLockPrompt:enabled"/> <int value="-949956361" label="ControlledFrame:disabled"/> + <int value="-949289795" label="PdfInk2:disabled"/> <int value="-949178861" label="enable-new-avatar-menu"/> <int value="-948930847" label="EnableOopPrintDrivers:enabled"/> <int value="-948684341" label="OmniboxBlurWithEscape:enabled"/> @@ -19137,6 +19136,8 @@ <int value="-914210146" label="enable-web-based-signin"/> <int value="-914097698" label="EnableDbusAndX11StatusIcons:disabled"/> <int value="-913925109" label="FilesExtractArchive:disabled"/> + <int value="-913908307" + label="EnableFingerprintingProtectionFilter:disabled"/> <int value="-913629421" label="CastStreamingVp8:enabled"/> <int value="-913571703" label="TabAndLinkDragDropAndroid:enabled"/> <int value="-913294939" label="DriveFS:enabled"/> @@ -19520,6 +19521,7 @@ <int value="-741751264" label="SafetyCheckPermissions:disabled"/> <int value="-740850824" label="PrefetchNotificationSchedulingIntegration:enabled"/> + <int value="-740300751" label="TabStripGroupCollapseAndroid:enabled"/> <int value="-738957187" label="OmniboxUIExperimentSwapTitleAndUrl:disabled"/> <int value="-738264153" label="WaylandScreenCoordinatesEnabled:enabled"/> <int value="-737740161" label="SupportForAddPasswordsInSettings:enabled"/> @@ -20093,6 +20095,7 @@ <int value="-481626345" label="WebAppEnableScopeExtensions:enabled"/> <int value="-481238673" label="EnableAndroidGamepadVibration:disabled"/> <int value="-480263549" label="AutofillShadowDOM:disabled"/> + <int value="-479908983" label="PrintPreviewCrosPrimary:disabled"/> <int value="-479601398" label="InfoCardAcknowledgementTracking:enabled"/> <int value="-479065716" label="CloudGamingDevice:disabled"/> <int value="-478462945" label="enable-ephemeral-apps"/> @@ -20458,6 +20461,7 @@ <int value="-314605926" label="protect-sync-credential-on-reauth:enabled"/> <int value="-314566497" label="BrokerFileOperationsOnDiskCacheInNetworkService:enabled"/> + <int value="-314102877" label="PdfInk2:enabled"/> <int value="-313812707" label="VideoTutorials:disabled"/> <int value="-312144677" label="TFLiteLanguageDetectionEnabled:disabled"/> <int value="-311509777" @@ -20688,8 +20692,6 @@ <int value="-215580565" label="OmniboxEnableClipboardProviderImageSuggestions:disabled"/> <int value="-215534141" label="NativeWindowNavButtons:enabled"/> - <int value="-215370258" - label="EnableFingerprintingProtectionBlockList:disabled"/> <int value="-215103767" label="ShoppingList:disabled"/> <int value="-215048684" label="NtpComprehensiveThemeRealbox:disabled"/> <int value="-214859547" label="OmniboxActionsUISimplification:enabled"/> @@ -20757,6 +20759,7 @@ <int value="-180481252" label="CompositorThreadedScrollbarScrolling:enabled"/> <int value="-180056644" label="HomeButtonWithText:disabled"/> <int value="-179580377" label="CrossOriginOpenerPolicy:enabled"/> + <int value="-178744239" label="DriveFsMirroring:enabled"/> <int value="-178364053" label="TerminalSystemAppLegacySettings:enabled"/> <int value="-178359490" label="DrawImmediatelyWhenInteractive:enabled"/> <int value="-177974995" label="CrostiniShowMicSetting:disabled"/> @@ -21321,6 +21324,7 @@ <int value="65750425" label="OmniboxMostVisitedTilesDynamicSpacing:disabled"/> <int value="66897259" label="ModalPermissionDialogView:enabled"/> <int value="67639499" label="stop-loading-in-background:disabled"/> + <int value="68506319" label="TabStripGroupCollapseAndroid:disabled"/> <int value="69571279" label="ExperimentalRgbKeyboardPatterns:disabled"/> <int value="69778786" label="NotificationPermissionVariant:disabled"/> <int value="71290103" label="ArcNearbySharing:enabled"/> @@ -21793,6 +21797,7 @@ <int value="282692100" label="SubframeShutdownDelay:disabled"/> <int value="283182071" label="SecurityInterstitialsDarkMode:enabled"/> <int value="283232244" label="OmniboxUIExperimentNarrowDropdown:enabled"/> + <int value="283822478" label="PrintPreviewCrosPrimary:enabled"/> <int value="284631756" label="EnableBrightnessControlInSettings:disabled"/> <int value="284756778" label="SearchCustomizableShortcutsInLauncher:disabled"/> @@ -22912,6 +22917,7 @@ <int value="768855962" label="PaymentRequestBasicCard:enabled"/> <int value="768900239" label="ArcSwitchToKeyMintOnTOverride:disabled"/> <int value="770680432" label="DecodeLossyWebPImagesToYUV:enabled"/> + <int value="771216808" label="EnableAutomaticSharedImageManagement:enabled"/> <int value="772272625" label="simplify-https-indicator"/> <int value="772348426" label="AffiliationBasedMatching:enabled"/> <int value="772360813" @@ -24302,8 +24308,6 @@ <int value="1402940985" label="kScrollableTabStripWithDragging:disabled"/> <int value="1403195370" label="ArcCupsApi:enabled"/> <int value="1403792475" label="ShareMenu:enabled"/> - <int value="1404592684" - label="LegacyTechReportEnableCookieIssueReports:enabled"/> <int value="1404726271" label="ReduceHorizontalFlingVelocity:enabled"/> <int value="1405459667" label="enable-fast-text-autosizing"/> <int value="1406046556" label="enable-slimming-paint-v175"/> @@ -24666,6 +24670,7 @@ <int value="1569327162" label="ButterOnDesktopFollowup:enabled"/> <int value="1570051274" label="ProductSpecifications:disabled"/> <int value="1570178909" label="NewOverviewLayout:enabled"/> + <int value="1570786077" label="EnableFingerprintingProtectionFilter:enabled"/> <int value="1571640975" label="EcheLauncherIconsInMoreAppsButton:enabled"/> <int value="1571998166" label="DetectingHeavyPages:disabled"/> <int value="1572464760" label="pwa-update-dialog-for-name-and-icon:disabled"/> @@ -25266,6 +25271,7 @@ <int value="1823337908" label="SmartDim20190221:enabled"/> <int value="1823457914" label="UsernameFirstFlowWithIntermediateValues:disabled"/> + <int value="1823816639" label="DriveFsMirroring:disabled"/> <int value="1824332134" label="EnableDnsProxy:disabled"/> <int value="1824931483" label="EnableHistoryFaviconsGoogleServerQuery:disabled"/> @@ -33321,6 +33327,9 @@ <int value="14" label="CERT_VALIDITY_TOO_LONG"/> <int value="15" label="CERTIFICATE_TRANSPARENCY_REQUIRED"/> <int value="16" label="CERT_SYMANTEC_LEGACY"/> + <int value="17" label="CERT_KNOWN_INTERCEPTION_BLOCKED"/> + <int value="18" label="LEGACY_TLS"/> + <int value="19" label="CERT_NON_UNIQUE_NAME"/> </enum> <enum name="SSLSignatureAlgorithm"> @@ -36234,6 +36243,7 @@ <int value="85" label="Show reading mode side panel"/> <int value="86" label="Open Safety Menu settings UI"/> <int value="87" label="Show password manager checkup"/> + <int value="88" label="Set browser as default"/> </enum> <enum name="XHRPageDismissalState">
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index d81ea7e3..ad6fba2 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1744,6 +1744,17 @@ </summary> </histogram> +<histogram name="Accessibility.PDF.IsPDFTagged" enum="BooleanExists" + expires_after="2025-02-28"> + <owner>dtseng@chromium.org</owner> + <owner>kyungjunlee@google.com</owner> + <owner>chrome-a11y-core@google.com</owner> + <summary> + When a PDF is constructed for accessibility, true if the PDF is tagged as + specified by ISO 14289-1 (PDF/UA). + </summary> +</histogram> + <histogram name="Accessibility.PdfOcr.ActiveWhenInaccessiblePdfOpened" enum="BooleanExists" expires_after="2025-02-28"> <owner>kyungjunlee@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 20db0bd..cf5d815 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -6072,6 +6072,7 @@ <variant name="Clipboard"/> <variant name="Date"/> <variant name="Drive"/> + <variant name="Editor"/> <variant name="Emoji"/> <variant name="File"/> <variant name="Gif"/> @@ -7164,6 +7165,17 @@ </summary> </histogram> +<histogram name="Ash.Shelf.DefaultApps.Pinned" enum="DefaultAppName" + expires_after="2025-02-22"> + <owner>dmblack@google.com</owner> + <owner>tbarzic@chromium.org</owner> + <owner>chromeos-launcher@google.com</owner> + <summary> + Records the default apps that are pinned to the shelf. This metric is + recorded with every UMA log upload. + </summary> +</histogram> + <histogram name="Ash.Shelf.Menu.NumItemsEnabledUponSelection" units="Count" expires_after="2025-02-22"> <owner>anasalazar@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml index 7eae8e2..892e5a9 100644 --- a/tools/metrics/histograms/metadata/extensions/histograms.xml +++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -541,6 +541,19 @@ </summary> </histogram> +<histogram name="Extensions.CookieAPIPartitionKeyWellFormatted" + enum="BooleanEnabled" expires_after="2025-04-18"> + <owner>arichiv@google.com</owner> + <owner>src/net/cookies/OWNERS</owner> + <summary> + Emits when a valid partitionKey argument is supplied to chrome.cookies APIs + getting/editing cookies. + + The enum value is true when the partitonKey is 'well formatted' (identical + to a SchemefulSite) and false when the partitonKey is otherwise coercible. + </summary> +</histogram> + <histogram name="Extensions.CorruptExtensionDisabledReason" enum="CorruptExtensionDisabledReason" expires_after="2024-11-20"> <owner>jlulejian@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml index 065fa18b..beee8d65 100644 --- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml +++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -28,9 +28,6 @@ </variants> <variants name="IPHFeature"> - <variant name="IPH_3pcdUserBypass" - summary="promo for bypassing cookie blocking during third-party cookie - deprecation"/> <variant name="IPH_AdaptiveButtonInTopToolbarCustomization_AddToBookmarks" summary="the add to bookmarks adaptive button in the top toolbar"/> <variant name="IPH_AdaptiveButtonInTopToolbarCustomization_NewTab"
diff --git a/tools/metrics/histograms/metadata/nearby/histograms.xml b/tools/metrics/histograms/metadata/nearby/histograms.xml index d98f33f3..0240734 100644 --- a/tools/metrics/histograms/metadata/nearby/histograms.xml +++ b/tools/metrics/histograms/metadata/nearby/histograms.xml
@@ -455,6 +455,32 @@ </histogram> <histogram + name="Nearby.Presence.Credentials.Storage.LocalSharedCredentials.Count" + units="count" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total number of local shared credentials stored in the local + shared credential database of the Nearby Presence Credential Storage + component. Emitted to once each time Nearby Presence is initialized in the + utility process. + </summary> +</histogram> + +<histogram + name="Nearby.Presence.Credentials.Storage.LocalSharedCredentials.Size" + units="KB" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total size of local shared credentials stored in the local + shared credential database of the Nearby Presence Credential Storage + component. Emitted to once each time Nearby Presence is initialized in the + utility process. + </summary> +</histogram> + +<histogram name="Nearby.Presence.Credentials.Storage.PrivateDatabaseInitializationDuration" units="microseconds" expires_after="2025-04-10"> <owner>hansberry@chromium.org</owner> @@ -507,6 +533,45 @@ </histogram> <histogram + name="Nearby.Presence.Credentials.Storage.RemoteSharedCredentials.Count" + units="count" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total number of remote shared credentials stored in the remote + shared credential database of the Nearby Presence Credential Storage + component. Emitted to once each time Nearby Presence is initialized in the + utility process. + </summary> +</histogram> + +<histogram + name="Nearby.Presence.Credentials.Storage.RemoteSharedCredentials.Size" + units="KB" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the total size of remote shared credentials stored in the remote + shared credential database of the Nearby Presence Credential Storage + component. Emitted to once each time Nearby Presence is initialized in the + utility process. + </summary> +</histogram> + +<histogram + name="Nearby.Presence.Credentials.Storage.RetrieveLocalPublicCredentials.Result" + enum="BooleanSuccess" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the result of an attempt at retrieving credentials from the local + public credential database of the Nearby Presence Credential Storage + component. Emitted after an attempt to retrieve credentials from the local + public credential database completes. + </summary> +</histogram> + +<histogram name="Nearby.Presence.Credentials.Storage.RetrieveLocalPublicCredentialsDuration" units="microseconds" expires_after="2025-04-10"> <owner>hansberry@chromium.org</owner> @@ -521,6 +586,19 @@ </histogram> <histogram + name="Nearby.Presence.Credentials.Storage.RetrievePrivateCredentials.Result" + enum="BooleanSuccess" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the result of an attempt at retrieving credentials from the private + credential database of the Nearby Presence Credential Storage component. + Emitted after an attempt to retrieve credentials from the private credential + database completes. + </summary> +</histogram> + +<histogram name="Nearby.Presence.Credentials.Storage.RetrievePrivateCredentialsDuration" units="microseconds" expires_after="2025-04-10"> <owner>hansberry@chromium.org</owner> @@ -535,6 +613,19 @@ </histogram> <histogram + name="Nearby.Presence.Credentials.Storage.RetrieveRemotePublicCredentials.Result" + enum="BooleanSuccess" expires_after="2025-04-10"> + <owner>hansberry@chromium.org</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Records the result of an attempt at retrieving credentials from the remote + public credential database of the Nearby Presence Credential Storage + component. Emitted after an attempt to retrieve credentials from the remote + public credential database completes. + </summary> +</histogram> + +<histogram name="Nearby.Presence.Credentials.Storage.RetrieveRemotePublicCredentialsDuration" units="microseconds" expires_after="2025-04-10"> <owner>hansberry@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/enums.xml b/tools/metrics/histograms/metadata/others/enums.xml index 1ab2c0b..c9d77fa 100644 --- a/tools/metrics/histograms/metadata/others/enums.xml +++ b/tools/metrics/histograms/metadata/others/enums.xml
@@ -40,6 +40,19 @@ <int value="3" label="Wayland"/> </enum> +<enum name="RedactionToolCaller"> + <summary>The caller of the redaction tool.</summary> + <int value="1" label="System Logs Uploader"/> + <int value="2" label="System Logs Fetcher"/> + <int value="3" label="Support Tool"/> + <int value="4" label="Error Reporting"/> + <int value="5" label="Feedback Tool"/> + <int value="6" label="Browser System Logs"/> + <int value="7" label="Unit Tests"/> + <int value="8" label="Undetermined"/> + <int value="9" label="Unknown"/> +</enum> + <enum name="SilentPushEvent"> <int value="0" label="New Silent Push request"/> <int value="1" label="Notification enforcement skipped"/>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index d82b8d6..0543c28 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -5037,7 +5037,7 @@ </histogram> <histogram name="Drive.PushNotificationRegistered" enum="BooleanRegistered" - expires_after="M137"> + expires_after="2024-05-19"> <owner>simmonsjosh@google.com</owner> <owner>src/ui/file_manager/OWNERS</owner> <summary> @@ -5811,6 +5811,17 @@ </summary> </histogram> +<histogram name="Feedback.RedactionTool.Caller" enum="RedactionToolCaller" + expires_after="2024-09-15"> + <owner>rohkap@google.com</owner> + <owner>dpchromeos-core-eng@google.com</owner> + <summary> + Records which caller invoked the redaction tool. This helps us determine + where the most redactions are happening and so places emitting most PII in + logs. + </summary> +</histogram> + <histogram name="Feedback.RedactionTool.CreditCardMatch" enum="CreditCardDetection" expires_after="2024-09-01"> <owner>cschlosser@chromium.org</owner> @@ -7250,7 +7261,7 @@ </summary> </histogram> -<histogram name="LoadingPredictor.PredictorDatabaseFileSize" units="KB" +<histogram name="LoadingPredictor.PredictorDatabaseFileSize" units="KiB" expires_after="2024-07-09"> <owner>yoichio@chromium.org</owner> <owner>chrome-loading@chromium.org</owner> @@ -10168,7 +10179,7 @@ </histogram> <histogram name="SiteIsolatedCodeCache.JS.Behaviour" - enum="SiteIsolatedCodeCacheJSBehaviour" expires_after="2024-04-03"> + enum="SiteIsolatedCodeCacheJSBehaviour" expires_after="2025-04-18"> <owner>awillia@chromium.org</owner> <owner>loading-dev@chromium.org</owner> <summary> @@ -10243,7 +10254,7 @@ </histogram> <histogram name="SiteIsolatedCodeCache.WASM.Behaviour" - enum="SiteIsolatedCodeCacheWASMBehaviour" expires_after="2024-10-06"> + enum="SiteIsolatedCodeCacheWASMBehaviour" expires_after="2025-04-18"> <owner>awillia@chromium.org</owner> <owner>loading-dev@chromium.org</owner> <summary> @@ -12418,6 +12429,7 @@ <variant name="RestoreTab"/> <variant name="SavePage"/> <variant name="SendToDevices"/> + <variant name="SetBrowserAsDefault"/> <variant name="Settings"/> <variant name="ShowAddresses"/> <variant name="ShowBookmarkBar"/>
diff --git a/tools/metrics/histograms/metadata/printing/enums.xml b/tools/metrics/histograms/metadata/printing/enums.xml index 9dd61ab..8d022a8 100644 --- a/tools/metrics/histograms/metadata/printing/enums.xml +++ b/tools/metrics/histograms/metadata/printing/enums.xml
@@ -26,16 +26,6 @@ <enums> -<enum name="IppVersion"> - <int value="0" label="Error">Failed to parse version</int> - <int value="1" label="Unknown">Version value not recognized</int> - <int value="2" label="IPP 1.0">IPP 1.0</int> - <int value="3" label="IPP 1.1">IPP 1.1</int> - <int value="4" label="IPP 2.0">IPP 2.0</int> - <int value="5" label="IPP 2.1">IPP 2.1</int> - <int value="6" label="IPP 2.2">IPP 2.2</int> -</enum> - <enum name="PrintAttemptOutcome"> <int value="0" label="Cancelled print button disabled"/> <int value="1" label="Cancelled no printers available"/>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml index 416cc37..f6b13cc 100644 --- a/tools/metrics/histograms/metadata/printing/histograms.xml +++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -132,18 +132,6 @@ </summary> </histogram> -<histogram name="Printing.CUPS.HighestIppVersion" enum="IppVersion" - expires_after="2022-04-17"> - <owner>skau@chromium.org</owner> - <owner>pawliczek@chromium.org</owner> - <summary> - Records the highest IPP version reported by a printer when we query the - printer for attributes. Useful to understand the population of printers - currently used. Recorded during printer setup for IPP printers. Recorded - only on ChromeOS. - </summary> -</histogram> - <histogram name="Printing.CUPS.IppAttributesSuccess" enum="BooleanSuccess" expires_after="2024-10-13"> <owner>bmgordon@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/quickstart/enums.xml b/tools/metrics/histograms/metadata/quickstart/enums.xml index e6e56308..7870a49 100644 --- a/tools/metrics/histograms/metadata/quickstart/enums.xml +++ b/tools/metrics/histograms/metadata/quickstart/enums.xml
@@ -38,7 +38,7 @@ <int value="2" label="Automatic Resume After Update"/> </enum> -<enum name="QuickStartFastPairAdvertisingEndedErrorCode"> +<enum name="QuickStartFastPairAdvertisingErrorCode"> <int value="0" label="Error: Unsupported platform"/> <int value="1" label="Error: Advertisement already exists"/> <int value="2" label="Error: Advertisement does not exist"/> @@ -106,6 +106,18 @@ <int value="7" label="Bootstrap State Complete"/> </enum> +<enum name="QuickStartNearbyConnectionsAdvertisingErrorCode"> + <int value="0" label="Error occurred without any more information"/> + <int value="1" label="Out of order API call"/> + <int value="2" label="Already active with another Strategy"/> + <int value="3" label="Already advertising"/> + <int value="4" label="Bluetooth error"/> + <int value="5" label="BLE error"/> + <int value="6" label="Unknown failure"/> + <int value="7" label="Connection timed out"/> + <int value="8" label="Another unexpected error occurred"/> +</enum> + <enum name="QuickStartScreenName"> <int value="0" label="Other"/> <int value="1" label="None"/>
diff --git a/tools/metrics/histograms/metadata/quickstart/histograms.xml b/tools/metrics/histograms/metadata/quickstart/histograms.xml index a2b9f28a..b85b93c 100644 --- a/tools/metrics/histograms/metadata/quickstart/histograms.xml +++ b/tools/metrics/histograms/metadata/quickstart/histograms.xml
@@ -115,21 +115,20 @@ <owner>joeantonetti@google.com</owner> <owner>chromeos-cross-device-eng@google.com</owner> <summary> - Time elapsed from attempting to start Fast Pair Advertising to it ending or - an error occurring. Recorded when unregistering the advertisement or when - there's an error attempting to register the advertisement. + Time elapsed from attempting to start Fast Pair Advertising to it ending. + Recorded after unregistering the advertisement. It is not recorded when an + error occurs attempting to register/unregister the advertisement. </summary> </histogram> <histogram name="QuickStart.FastPairAdvertisementEnded.ErrorCode" - enum="QuickStartFastPairAdvertisingEndedErrorCode" - expires_after="2024-12-01"> + enum="QuickStartFastPairAdvertisingErrorCode" expires_after="2024-12-01"> <owner>bhartmire@google.com</owner> <owner>joeantonetti@google.com</owner> <owner>chromeos-cross-device-eng@google.com</owner> <summary> - Reason a Fast Pair BLE advertisment failed to register. Recorded whenever a - Bluetooth Advertisement error occurs after attempting to register the + Reason a Fast Pair BLE advertisment failed to unregister. Recorded whenever + a Bluetooth Advertisement error occurs after attempting to unregister the advertisement. </summary> </histogram> @@ -140,20 +139,33 @@ <owner>joeantonetti@google.com</owner> <owner>chromeos-cross-device-eng@google.com</owner> <summary> - Whether Fast Pair advertising was successful. Recorded when unregistering - the advertisement or when there's an error attempting to register the - advertisement. + Whether unregistering the Fast Pair advertisement was successful. Recorded + after unregistering the advertisement or when there's an error attempting to + unregister the advertisement. </summary> </histogram> -<histogram name="QuickStart.FastPairAdvertisementStarted" - enum="BooleanAttempted" expires_after="2024-12-01"> +<histogram name="QuickStart.FastPairAdvertisementStarted.ErrorCode" + enum="QuickStartFastPairAdvertisingErrorCode" expires_after="2024-12-01"> <owner>bhartmire@google.com</owner> <owner>joeantonetti@google.com</owner> <owner>chromeos-cross-device-eng@google.com</owner> <summary> - Whether Fast Pair advertising is started. Recorded before attempting to - register advertisement. + Reason a Fast Pair BLE advertisment failed to register. Recorded whenever a + Bluetooth Advertisement error occurs after attempting to register the + advertisement. + </summary> +</histogram> + +<histogram name="QuickStart.FastPairAdvertisementStarted.Succeeded" + enum="BooleanSuccess" expires_after="2024-12-01"> + <owner>bhartmire@google.com</owner> + <owner>joeantonetti@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Whether Fast Pair advertising is started successfully. Recorded after the + advertisement is succesfully registered or when there's an error attempting + to register the advertisement. </summary> </histogram> @@ -345,6 +357,68 @@ </summary> </histogram> +<histogram name="QuickStart.NearbyConnectionsAdvertisementEnded.Duration" + units="ms" expires_after="2025-04-16"> + <owner>bhartmire@google.com</owner> + <owner>hansenmichael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Time elapsed during Nearby Connections advertisement. Recorded after + successfully stopping the advertisement. It is not recorded when an error + occurs attempting to start/stop the advertisement. + </summary> +</histogram> + +<histogram name="QuickStart.NearbyConnectionsAdvertisementEnded.ErrorCode" + enum="QuickStartNearbyConnectionsAdvertisingErrorCode" + expires_after="2025-04-16"> + <owner>bhartmire@google.com</owner> + <owner>hansenmichael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Reason a Nearby Connections advertisement failed to stop. Recorded whenever + a Nearby Connections error occurs after attempting to stop the + advertisement. + </summary> +</histogram> + +<histogram name="QuickStart.NearbyConnectionsAdvertisementEnded.Succeeded" + enum="BooleanSuccess" expires_after="2025-04-16"> + <owner>bhartmire@google.com</owner> + <owner>hansenmichael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Whether the Nearby Connections advertisement was successfully stopped. + Recorded after the advertisement succesfully stops or an error occurs after + attempting to stop the advertisement. + </summary> +</histogram> + +<histogram name="QuickStart.NearbyConnectionsAdvertisementStarted.ErrorCode" + enum="QuickStartNearbyConnectionsAdvertisingErrorCode" + expires_after="2025-04-16"> + <owner>bhartmire@google.com</owner> + <owner>hansenmichael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Reason a Nearby Connections advertisement failed to start. Recorded whenever + a Nearby Connections error occurs after attempting to start the + advertisement. + </summary> +</histogram> + +<histogram name="QuickStart.NearbyConnectionsAdvertisementStarted.Succeeded" + enum="BooleanSuccess" expires_after="2025-04-16"> + <owner>bhartmire@google.com</owner> + <owner>hansenmichael@google.com</owner> + <owner>chromeos-cross-device-eng@google.com</owner> + <summary> + Whether Nearby Connections advertising is started successfully. Recorded + when advertising successfully starts or when an error occurs after + attempting to start. + </summary> +</histogram> + <histogram name="QuickStart.ScreenClosed.{ScreenName}.Reason" enum="ScreenClosedReason" expires_after="2025-04-09"> <owner>bhartmire@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/sync/enums.xml b/tools/metrics/histograms/metadata/sync/enums.xml index bb365100..c077002 100644 --- a/tools/metrics/histograms/metadata/sync/enums.xml +++ b/tools/metrics/histograms/metadata/sync/enums.xml
@@ -545,6 +545,7 @@ label="ProfileDefaultContentSettingValuesTrackingProtection"/> <int value="100276" label="ShowForwardButton"/> <int value="100277" label="AccessibilityMagnifierFollowsSts"/> + <int value="100278" label="AccessibilityReadAnythingLanguagesEnabled"/> <int value="200000" label="ArticlesForYouEnabled"/> <int value="200001" label="ContextualSearchEnabled_IOS"/> <int value="200002" label="DefaultCharset_IOS"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 6c921f1..ebc12f0 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -9979,6 +9979,19 @@ </history> </aggregation> </metric> + <metric name="DetectionTriggeredOnDomContentLoaded" enum="Boolean"> + <summary> + Whether PIX code detection was triggered on DOMContentLoaded instead of + DidFinishLoad. + </summary> + <aggregation> + <history> + <statistics> + <enumeration/> + </statistics> + </history> + </aggregation> + </metric> <metric name="LatencyInMillis"> <summary> The duration (in milliseconds) for how long it took to scan the document
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index 616749e1..470146a2 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -491,6 +491,8 @@ ]) _WIN_11_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([ 'blink_perf.display_locking', + 'rendering.desktop', + 'system_health.common_desktop', 'v8.runtime_stats.top_25', ]) _WIN_11_EXECUTABLE_CONFIGS = frozenset([
diff --git a/tools/perf/core/shard_maps/linux-perf_map.json b/tools/perf/core/shard_maps/linux-perf_map.json index ce8a2ca1..0f868a3 100644 --- a/tools/perf/core/shard_maps/linux-perf_map.json +++ b/tools/perf/core/shard_maps/linux-perf_map.json
@@ -34,10 +34,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -99,10 +99,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -158,10 +158,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -220,10 +220,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -273,10 +273,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -335,10 +335,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -400,10 +400,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -462,10 +462,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -517,10 +517,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -564,10 +564,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -603,10 +603,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -653,10 +653,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -683,10 +683,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -713,10 +713,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -743,10 +743,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -773,10 +773,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -803,10 +803,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -833,10 +833,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": { @@ -908,10 +908,10 @@ "speedometer": { "abridged": false }, - "speedometer2": { + "speedometer2-nominorms": { "abridged": false }, - "speedometer2-nominorms": { + "speedometer2": { "abridged": false }, "speedometer2-predictable": {
diff --git a/tools/perf/core/shard_maps/timing_data/win-11-perf_timing.json b/tools/perf/core/shard_maps/timing_data/win-11-perf_timing.json index 782e1a1..b2476cc 100644 --- a/tools/perf/core/shard_maps/timing_data/win-11-perf_timing.json +++ b/tools/perf/core/shard_maps/timing_data/win-11-perf_timing.json
@@ -1,14 +1,14 @@ [ { - "duration": "10.0", + "duration": "9.0", "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.275220.MYBESTOPTION.IT4/B8455269.126839257;sz=970x250" }, { - "duration": "9.0", + "duration": "10.0", "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.275220.MYBESTOPTION.IT4/B9340305.127461685;sz=970x250" }, { - "duration": "15.0", + "duration": "10.0", "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.275220.MYBESTOPTION.IT4/B9340305.127562781;sz=970x250" }, { @@ -16,47 +16,43 @@ "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.275220.MYBESTOPTION.IT4/B9340305.128470354;sz=300x600" }, { - "duration": "11.0", + "duration": "10.0", "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.275220.MYBESTOPTION.IT4/B9340305.128710365;sz=970x250" }, { - "duration": "10.0", + "duration": "9.0", "name": "ad_frames.fencedframe/fencedframe: https://ad.doubleclick.net/ddm/adi/N378.3159.GOOGLE3/B9340305.138620671;sz=970x250" }, { - "duration": "33.0", + "duration": "35.0", "name": "blink_perf.accessibility/build-table.html" }, { - "duration": "21.0", + "duration": "22.0", "name": "blink_perf.accessibility/focus-links.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.accessibility/insert-block-child-after-many-inline-children.html" }, { - "duration": "21.0", + "duration": "22.0", "name": "blink_perf.accessibility/line-breaks.html" }, { - "duration": "22.0", + "duration": "21.0", "name": "blink_perf.accessibility/location-changes-css-animation.html" }, { - "duration": "28.0", + "duration": "36.0", "name": "blink_perf.accessibility/location-changes-js-animation.html" }, { - "duration": "35.0", - "name": "blink_perf.accessibility/location-changes-scrolling.html" - }, - { - "duration": "29.0", + "duration": "30.0", "name": "blink_perf.accessibility/many-nodes-toggle-content-visibility-auto.html" }, { - "duration": "23.0", + "duration": "24.0", "name": "blink_perf.accessibility/many-nodes-toggle-content-visibility-hidden.html" }, { @@ -64,7 +60,7 @@ "name": "blink_perf.accessibility/many-nodes-toggle-display-none-in-focusable.html" }, { - "duration": "21.0", + "duration": "22.0", "name": "blink_perf.accessibility/many-nodes-toggle-display-none.html" }, { @@ -72,19 +68,19 @@ "name": "blink_perf.accessibility/many-text-changes-deep-block-subtree.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.accessibility/many-text-changes-deep-hidden-subtree.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.accessibility/many-text-changes-deep-inline-subtree.html" }, { - "duration": "31.0", + "duration": "30.0", "name": "blink_perf.accessibility/many-text-changes-small-wait-between.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.accessibility/slot-updates.html" }, { @@ -92,11 +88,11 @@ "name": "blink_perf.accessibility/text-changes-ignored-in-focusable.html" }, { - "duration": "23.0", + "duration": "24.0", "name": "blink_perf.accessibility/text-changes-unignored-in-focusable.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.accessibility/textarea-append.html" }, { @@ -104,11 +100,11 @@ "name": "blink_perf.accessibility/unassignable-slots-deep-tree.html" }, { - "duration": "23.0", + "duration": "28.0", "name": "blink_perf.accessibility/unassignable-slots-focusable-containers.html" }, { - "duration": "21.0", + "duration": "23.0", "name": "blink_perf.accessibility/unassignable-slots-wide-tree.html" }, { @@ -128,7 +124,7 @@ "name": "blink_perf.bindings/dom-attribute-on-prototoype.html" }, { - "duration": "9.0", + "duration": "6.0", "name": "blink_perf.bindings/first-child.html" }, { @@ -140,7 +136,7 @@ "name": "blink_perf.bindings/gc-mini-tree.html" }, { - "duration": "10.0", + "duration": "12.0", "name": "blink_perf.bindings/gc-tree.html" }, { @@ -180,7 +176,7 @@ "name": "blink_perf.bindings/named-property-enumerator.html" }, { - "duration": "12.0", + "duration": "9.0", "name": "blink_perf.bindings/node-list-access.html" }, { @@ -196,7 +192,7 @@ "name": "blink_perf.bindings/sequence-conversion-array.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.bindings/sequence-conversion-custom-iterator.html" }, { @@ -268,6 +264,14 @@ "name": "blink_perf.bindings/undefined-id-getter.html" }, { + "duration": "0.0", + "name": "blink_perf.bindings/wasm_webgl_no_js.html" + }, + { + "duration": "0.0", + "name": "blink_perf.bindings/wasm_webgl_through_js.html" + }, + { "duration": "1.0", "name": "blink_perf.bindings/worker-structured-clone-different-payloads.html" }, @@ -388,11 +392,11 @@ "name": "blink_perf.css/ChangeStyleMultipleQualifiedDataAttributesWithValuesSelector.html" }, { - "duration": "4.0", + "duration": "3.0", "name": "blink_perf.css/ChangeStyleNestedPseudoSelector.html" }, { - "duration": "8.0", + "duration": "6.0", "name": "blink_perf.css/ChangeStyleNewRuleInExistingStylesheet.html" }, { @@ -424,11 +428,11 @@ "name": "blink_perf.css/ChangeStyleSingleNthChildSelector.html" }, { - "duration": "4.0", + "duration": "3.0", "name": "blink_perf.css/ChangeStyleSinglePseudoSelector.html" }, { - "duration": "4.0", + "duration": "3.0", "name": "blink_perf.css/ChangeStyleUniversalSelector.html" }, { @@ -436,7 +440,7 @@ "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeSelector.html" }, { - "duration": "4.0", + "duration": "3.0", "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeWithValueSelector.html" }, { @@ -456,7 +460,7 @@ "name": "blink_perf.css/CustomPropertiesCascade.html" }, { - "duration": "1.0", + "duration": "2.0", "name": "blink_perf.css/CustomPropertiesDependency.html" }, { @@ -484,7 +488,7 @@ "name": "blink_perf.css/ExplicitInheritance.html" }, { - "duration": "7.0", + "duration": "8.0", "name": "blink_perf.css/FocusUpdate.html" }, { @@ -500,7 +504,7 @@ "name": "blink_perf.css/HasDescendantInvalidationAllSubjects.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.css/HasDescendantInvalidationMultipleSubjects.html" }, { @@ -508,7 +512,7 @@ "name": "blink_perf.css/HasDescendantInvalidationWith1NonMatchingHasRule.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.css/HasDescendantInvalidationWithMultipleNonMatchingHasRules.html" }, { @@ -540,7 +544,7 @@ "name": "blink_perf.css/HighlightInheritanceRecalc.html" }, { - "duration": "7.0", + "duration": "5.0", "name": "blink_perf.css/HighlightInheritanceSelected.html" }, { @@ -556,7 +560,7 @@ "name": "blink_perf.css/ImplicitAtScopeMatching.html" }, { - "duration": "2.0", + "duration": "1.0", "name": "blink_perf.css/ImplicitScopeShared.html" }, { @@ -572,7 +576,7 @@ "name": "blink_perf.css/LoadSemanticPageExample.html" }, { - "duration": "21.0", + "duration": "24.0", "name": "blink_perf.css/ModifySelectorText.html" }, { @@ -604,7 +608,7 @@ "name": "blink_perf.css/ScrollbarPseudoSelector.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.css/SelectorCountScaling.html" }, { @@ -616,15 +620,15 @@ "name": "blink_perf.dom/custom-element-default-style.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.dom/deep-tree-clonenode.html" }, { - "duration": "21.0", + "duration": "20.0", "name": "blink_perf.dom/dom-parts-api-flat-append.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.dom/dom-parts-api-flat-clone.html" }, { @@ -632,31 +636,31 @@ "name": "blink_perf.dom/dom-parts-api-flat-parts.html" }, { - "duration": "25.0", + "duration": "22.0", "name": "blink_perf.dom/dom-parts-api-manual-append.html" }, { - "duration": "25.0", + "duration": "20.0", "name": "blink_perf.dom/dom-parts-api-manual-clone.html" }, { - "duration": "24.0", + "duration": "21.0", "name": "blink_perf.dom/dom-parts-api-manual-parts.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.dom/dom-parts-api-nested-append.html" }, { - "duration": "20.0", + "duration": "21.0", "name": "blink_perf.dom/dom-parts-api-nested-clone.html" }, { - "duration": "20.0", + "duration": "24.0", "name": "blink_perf.dom/dom-parts-api-nested-parts.html" }, { - "duration": "17.0", + "duration": "13.0", "name": "blink_perf.dom/insert-text-with-dir-auto.html" }, { @@ -676,7 +680,7 @@ "name": "blink_perf.dom/modify-element-title.html" }, { - "duration": "9.0", + "duration": "6.0", "name": "blink_perf.dom/replace-text-with-dir-auto.html" }, { @@ -688,7 +692,7 @@ "name": "blink_perf.dom/select-single-add.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.dom/select-single-remove.html" }, { @@ -768,7 +772,7 @@ "name": "blink_perf.layout/Shapes/MultipleShapes.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.layout/SimpleTextPathLineLayout.html" }, { @@ -776,7 +780,7 @@ "name": "blink_perf.layout/abspos.html" }, { - "duration": "8.0", + "duration": "7.0", "name": "blink_perf.layout/add-remove-inline-floats.html" }, { @@ -832,7 +836,7 @@ "name": "blink_perf.layout/css-contain-change-text-different-subtree-root.html" }, { - "duration": "2.0", + "duration": "3.0", "name": "blink_perf.layout/css-contain-change-text-without-subtree-root.html" }, { @@ -872,7 +876,7 @@ "name": "blink_perf.layout/editing_prepend.html" }, { - "duration": "9.0", + "duration": "8.0", "name": "blink_perf.layout/fit-content-change-available-size-blocks.html" }, { @@ -912,7 +916,7 @@ "name": "blink_perf.layout/flexbox-input.html" }, { - "duration": "8.0", + "duration": "7.0", "name": "blink_perf.layout/flexbox-lots-of-data.html" }, { @@ -1040,7 +1044,7 @@ "name": "blink_perf.layout/latin-ebook.html" }, { - "duration": "22.0", + "duration": "21.0", "name": "blink_perf.layout/layer-overhead.html" }, { @@ -1112,7 +1116,7 @@ "name": "blink_perf.layout/multicol/balance-tables-with-break-inside-avoidance.html" }, { - "duration": "6.0", + "duration": "7.0", "name": "blink_perf.layout/multicol/deeply-nested-tables-2.html" }, { @@ -1160,7 +1164,7 @@ "name": "blink_perf.layout/multicol/tall-content-short-columns-realistic.html" }, { - "duration": "8.0", + "duration": "9.0", "name": "blink_perf.layout/multicol/tall-content-short-columns.html" }, { @@ -1188,7 +1192,7 @@ "name": "blink_perf.layout/nested-tables-with-overflow-auto.html" }, { - "duration": "7.0", + "duration": "14.0", "name": "blink_perf.layout/ruby.html" }, { @@ -1204,7 +1208,7 @@ "name": "blink_perf.layout/text-wrap-balance.html" }, { - "duration": "6.0", + "duration": "2.0", "name": "blink_perf.layout/vertical-japanese-kokoro-insert.html" }, { @@ -1220,23 +1224,23 @@ "name": "blink_perf.layout/word-wrap-break-word.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.owp_storage/blob-perf-files.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.owp_storage/blob-perf-ipc.html" }, { - "duration": "8.0", + "duration": "6.0", "name": "blink_perf.owp_storage/blob-perf-shm.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.owp_storage/blob-perf-tiny.html" }, { - "duration": "8.0", + "duration": "7.0", "name": "blink_perf.owp_storage/idb-load-docs.html" }, { @@ -1244,7 +1248,11 @@ "name": "blink_perf.parser/css-parser-yui.html" }, { - "duration": "7.0", + "duration": "0.0", + "name": "blink_perf.parser/declarative-shadow-dom-cloning.html" + }, + { + "duration": "0.0", "name": "blink_perf.parser/declarative-shadow-dom.html" }, { @@ -1252,11 +1260,11 @@ "name": "blink_perf.parser/html-parser.html" }, { - "duration": "14.0", + "duration": "13.0", "name": "blink_perf.parser/html5-full-render.html" }, { - "duration": "16.0", + "duration": "14.0", "name": "blink_perf.parser/iframe-append-remove.html" }, { @@ -1300,7 +1308,7 @@ "name": "blink_perf.parser/query-selector-all-first.html" }, { - "duration": "7.0", + "duration": "6.0", "name": "blink_perf.parser/query-selector-all-id-deep.html" }, { @@ -1352,7 +1360,7 @@ "name": "blink_perf.parser/url-parser.html" }, { - "duration": "10.0", + "duration": "9.0", "name": "blink_perf.parser/xml-parser.html" }, { @@ -1400,15 +1408,15 @@ "name": "blink_perf.shadow_dom/imperative-api.html" }, { - "duration": "74.0", + "duration": "0.0", "name": "blink_perf.shadow_dom/imperative-shadow-dom-overhead.html" }, { - "duration": "62.0", + "duration": "0.0", "name": "blink_perf.shadow_dom/shadow-dom-overhead-iframe.html" }, { - "duration": "22.0", + "duration": "0.0", "name": "blink_perf.shadow_dom/shadow-dom-overhead.html" }, { @@ -1512,31 +1520,31 @@ "name": "blink_perf.shadow_dom/v1-small-shallow-layout.html" }, { - "duration": "8.0", + "duration": "7.0", "name": "blink_perf.webaudio/audio-buffer-source-node.html" }, { - "duration": "33.0", + "duration": "32.0", "name": "blink_perf.webaudio/audio-worklet-node.html" }, { - "duration": "34.0", + "duration": "32.0", "name": "blink_perf.webaudio/biquad-filter-node.html" }, { - "duration": "29.0", + "duration": "28.0", "name": "blink_perf.webaudio/dynamics-compressor-node-knee.html" }, { - "duration": "30.0", + "duration": "29.0", "name": "blink_perf.webaudio/dynamics-compressor-node-post-knee.html" }, { - "duration": "29.0", + "duration": "28.0", "name": "blink_perf.webaudio/dynamics-compressor-node-pre-knee.html" }, { - "duration": "35.0", + "duration": "33.0", "name": "blink_perf.webaudio/gain-node.html" }, { @@ -1584,7 +1592,7 @@ "name": "blink_perf.webcodecs/videoFrame-drawImage.html" }, { - "duration": "6.0", + "duration": "5.0", "name": "blink_perf.webcodecs/videoFrame-texImage2d.html" }, { @@ -1596,23 +1604,23 @@ "name": "blink_perf.webgl/binding-buffer-sub-data.html" }, { - "duration": "17.0", + "duration": "18.0", "name": "blink_perf.webgl/binding-draw-arrays.html" }, { - "duration": "3.0", + "duration": "8.0", "name": "blink_perf.webgl/binding-typed-array-uniforms.html" }, { - "duration": "5.0", + "duration": "4.0", "name": "blink_perf.webgl_fast_call/binding-bind-buffer.html" }, { - "duration": "5.0", + "duration": "1.0", "name": "blink_perf.webgl_fast_call/binding-buffer-sub-data.html" }, { - "duration": "18.0", + "duration": "17.0", "name": "blink_perf.webgl_fast_call/binding-draw-arrays.html" }, { @@ -1660,7 +1668,7 @@ "name": "desktop_ui/tab_search:clean_slate" }, { - "duration": "19.0", + "duration": "18.0", "name": "desktop_ui/tab_search:close_and_open:2020" }, { @@ -1672,7 +1680,7 @@ "name": "desktop_ui/tab_search:measure_memory:2tab_search" }, { - "duration": "12.0", + "duration": "11.0", "name": "desktop_ui/tab_search:measure_memory:3tab_search" }, { @@ -1692,7 +1700,7 @@ "name": "desktop_ui/tab_search:scroll_up_and_down:2020" }, { - "duration": "24.0", + "duration": "25.0", "name": "desktop_ui/tab_search:top10:2020" }, { @@ -1736,7 +1744,7 @@ "name": "dummy_benchmark.stable_benchmark_1/dummy_page.html" }, { - "duration": "78.0", + "duration": "76.0", "name": "jetstream2/JetStream2" }, { @@ -1744,7 +1752,7 @@ "name": "media.desktop/mse.html?media=aac_audio.mp4" }, { - "duration": "7.0", + "duration": "8.0", "name": "media.desktop/mse.html?media=aac_audio.mp4,h264_video.mp4" }, { @@ -1756,11 +1764,11 @@ "name": "media.desktop/mse.html?media=tulip0.av1.mp4" }, { - "duration": "8.0", + "duration": "7.0", "name": "media.desktop/mse.html?media=tulip2.vp9.webm" }, { - "duration": "128.0", + "duration": "127.0", "name": "media.desktop/video.html?src=boat_1080p60fps_vp9.webm" }, { @@ -1768,7 +1776,7 @@ "name": "media.desktop/video.html?src=crowd1080.mp4" }, { - "duration": "14.0", + "duration": "13.0", "name": "media.desktop/video.html?src=crowd1080.webm" }, { @@ -1796,7 +1804,7 @@ "name": "media.desktop/video.html?src=tulip0.av1.mp4" }, { - "duration": "5.0", + "duration": "4.0", "name": "media.desktop/video.html?src=tulip0.av1.mp4&seek" }, { @@ -1808,7 +1816,7 @@ "name": "media.desktop/video.html?src=tulip2.mp3&type=audio" }, { - "duration": "5.0", + "duration": "4.0", "name": "media.desktop/video.html?src=tulip2.mp3&type=audio&seek" }, { @@ -1824,7 +1832,7 @@ "name": "media.desktop/video.html?src=tulip2.ogg&type=audio" }, { - "duration": "5.0", + "duration": "4.0", "name": "media.desktop/video.html?src=tulip2.ogg&type=audio&seek" }, { @@ -1880,19 +1888,19 @@ "name": "octane/Octane" }, { - "duration": "34.0", + "duration": "33.0", "name": "power.desktop/TrivialAnimationPageSharedPageState" }, { - "duration": "38.0", + "duration": "35.0", "name": "power.desktop/TrivialBlinkingCursorPageSharedPageState" }, { - "duration": "34.0", + "duration": "33.0", "name": "power.desktop/TrivialBlurAnimationPageSharedPageState" }, { - "duration": "38.0", + "duration": "35.0", "name": "power.desktop/TrivialCanvasPageSharedPageState" }, { @@ -1900,19 +1908,19 @@ "name": "power.desktop/TrivialFullscreenVideoPageSharedPageState" }, { - "duration": "34.0", + "duration": "33.0", "name": "power.desktop/TrivialGifPageSharedPageState" }, { - "duration": "39.0", + "duration": "36.0", "name": "power.desktop/TrivialScrollingPageSharedPageState" }, { - "duration": "35.0", + "duration": "36.0", "name": "power.desktop/TrivialWebGLPageSharedPageState" }, { - "duration": "40.0", + "duration": "39.0", "name": "power.desktop/abcnews" }, { @@ -1932,7 +1940,7 @@ "name": "power.desktop/sina" }, { - "duration": "34.0", + "duration": "33.0", "name": "power.desktop/slideshare" }, { @@ -1940,7 +1948,7 @@ "name": "power.desktop/uol" }, { - "duration": "20.0", + "duration": "21.0", "name": "rasterize_and_record_micro.top_25/file://static_top_25/amazon.html" }, { @@ -2040,75 +2048,7 @@ "name": "rasterize_and_record_micro.top_25/file://static_top_25/youtube.html" }, { - "duration": "4.0", - "name": "rendering.desktop/camera_to_webgl" - }, - { - "duration": "4.0", - "name": "rendering.desktop/cnn_pinch_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/espn_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/espn_pinch_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/gmail_move_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_canvas_arcs" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_canvas_lines" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_design" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_images" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_leaves" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_multiply" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_paths" - }, - { - "duration": "4.0", - "name": "rendering.desktop/motionmark_fixed_2_seconds_suits" - }, - { - "duration": "4.0", - "name": "rendering.desktop/yahoo_news_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/yahoo_sports_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/youtube_2018" - }, - { - "duration": "4.0", - "name": "rendering.desktop/youtube_pinch_2018" - }, - { - "duration": "15.0", + "duration": "14.0", "name": "speedometer-future/http://browserbench.org/Speedometer/" }, { @@ -2120,82 +2060,18 @@ "name": "speedometer2-future/Speedometer2" }, { - "duration": "28.0", + "duration": "29.0", "name": "speedometer2/Speedometer2" }, { - "duration": "37.0", + "duration": "36.0", "name": "speedometer3-future/Speedometer3" }, { - "duration": "37.0", + "duration": "36.0", "name": "speedometer3/Speedometer3" }, { - "duration": "3.0", - "name": "system_health.common_desktop/browse:media:youtube:2019" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/browse:news:hackernews:2020" - }, - { - "duration": "9.0", - "name": "system_health.common_desktop/browse:social:tumblr_infinite_scroll:2018" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse:tech:discourse_infinite_scroll:2018" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse:tools:gmail-compose:2020" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse:tools:gmail-labelclick:2020" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse:tools:gmail-openconversation:2020" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse:tools:gmail-search:2020" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/browse:tools:sheets:2019" - }, - { - "duration": "4.0", - "name": "system_health.common_desktop/browse_accessibility:media:youtube" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/load:media:imgur:2018" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/load:tools:chat:2020" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/load:tools:docs:2019" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/load:tools:gmail:2019" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/long_running:tools:gmail-background" - }, - { - "duration": "3.0", - "name": "system_health.common_desktop/long_running:tools:gmail-foreground" - }, - { "duration": "24.0", "name": "system_health.memory_desktop/browse:media:googleplaystore:2021" }, @@ -2224,7 +2100,7 @@ "name": "system_health.memory_desktop/browse:media:youtubetv_watch:2020" }, { - "duration": "26.0", + "duration": "25.0", "name": "system_health.memory_desktop/browse:news:cnn:2021" }, { @@ -2296,7 +2172,7 @@ "name": "system_health.memory_desktop/browse:tools:gmail-search:2020" }, { - "duration": "7.0", + "duration": "6.0", "name": "system_health.memory_desktop/browse:tools:maps:2019" }, { @@ -2336,7 +2212,7 @@ "name": "system_health.memory_desktop/load:games:lazors" }, { - "duration": "12.0", + "duration": "11.0", "name": "system_health.memory_desktop/load:games:miniclip:2018" }, { @@ -2508,31 +2384,31 @@ "name": "system_health.memory_desktop/play:media:google_play_music" }, { - "duration": "35.0", + "duration": "36.0", "name": "system_health.memory_desktop/play:media:soundcloud:2018" }, { - "duration": "30.0", + "duration": "29.0", "name": "v8.browsing_desktop-future/browse:media:googleplaystore:2021" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:media:imgur" }, { - "duration": "83.0", + "duration": "82.0", "name": "v8.browsing_desktop-future/browse:media:pinterest:2018" }, { - "duration": "53.0", + "duration": "52.0", "name": "v8.browsing_desktop-future/browse:media:tumblr:2018" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:media:youtube:2019" }, { - "duration": "61.0", + "duration": "60.0", "name": "v8.browsing_desktop-future/browse:media:youtubetv:2019" }, { @@ -2540,27 +2416,27 @@ "name": "v8.browsing_desktop-future/browse:media:youtubetv_watch:2020" }, { - "duration": "44.0", + "duration": "39.0", "name": "v8.browsing_desktop-future/browse:news:cnn:2021" }, { - "duration": "51.0", + "duration": "47.0", "name": "v8.browsing_desktop-future/browse:news:flipboard:2020" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:news:hackernews:2020" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:news:nytimes:2020" }, { - "duration": "42.0", + "duration": "41.0", "name": "v8.browsing_desktop-future/browse:news:reddit:2020" }, { - "duration": "45.0", + "duration": "44.0", "name": "v8.browsing_desktop-future/browse:search:google:2020" }, { @@ -2568,7 +2444,7 @@ "name": "v8.browsing_desktop-future/browse:search:google_india:2021" }, { - "duration": "70.0", + "duration": "66.0", "name": "v8.browsing_desktop-future/browse:social:facebook_infinite_scroll:2018" }, { @@ -2576,19 +2452,19 @@ "name": "v8.browsing_desktop-future/browse:social:tumblr_infinite_scroll:2018" }, { - "duration": "40.0", + "duration": "39.0", "name": "v8.browsing_desktop-future/browse:social:twitter:2018" }, { - "duration": "56.0", + "duration": "55.0", "name": "v8.browsing_desktop-future/browse:social:twitter_infinite_scroll:2018" }, { - "duration": "18.0", + "duration": "13.0", "name": "v8.browsing_desktop-future/browse:tech:discourse_infinite_scroll:2018" }, { - "duration": "25.0", + "duration": "20.0", "name": "v8.browsing_desktop-future/browse:tools:autocad:2021" }, { @@ -2596,23 +2472,23 @@ "name": "v8.browsing_desktop-future/browse:tools:docs_scrolling" }, { - "duration": "5.0", + "duration": "13.0", "name": "v8.browsing_desktop-future/browse:tools:gmail-compose:2020" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:tools:gmail-labelclick:2020" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:tools:gmail-openconversation:2020" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:tools:gmail-search:2020" }, { - "duration": "11.0", + "duration": "9.0", "name": "v8.browsing_desktop-future/browse:tools:maps:2019" }, { @@ -2620,11 +2496,11 @@ "name": "v8.browsing_desktop-future/browse:tools:photoshop:2021" }, { - "duration": "63.0", + "duration": "62.0", "name": "v8.browsing_desktop-future/browse:tools:photoshop_warm:2021" }, { - "duration": "5.0", + "duration": "4.0", "name": "v8.browsing_desktop-future/browse:tools:sheets:2019" }, { @@ -2636,7 +2512,7 @@ "name": "v8.browsing_desktop/browse:media:imgur" }, { - "duration": "84.0", + "duration": "83.0", "name": "v8.browsing_desktop/browse:media:pinterest:2018" }, { @@ -2656,11 +2532,11 @@ "name": "v8.browsing_desktop/browse:media:youtubetv_watch:2020" }, { - "duration": "39.0", + "duration": "33.0", "name": "v8.browsing_desktop/browse:news:cnn:2021" }, { - "duration": "46.0", + "duration": "42.0", "name": "v8.browsing_desktop/browse:news:flipboard:2020" }, { @@ -2676,15 +2552,15 @@ "name": "v8.browsing_desktop/browse:news:reddit:2020" }, { - "duration": "45.0", + "duration": "48.0", "name": "v8.browsing_desktop/browse:search:google:2020" }, { - "duration": "31.0", + "duration": "30.0", "name": "v8.browsing_desktop/browse:search:google_india:2021" }, { - "duration": "65.0", + "duration": "61.0", "name": "v8.browsing_desktop/browse:social:facebook_infinite_scroll:2018" }, { @@ -2700,11 +2576,11 @@ "name": "v8.browsing_desktop/browse:social:twitter_infinite_scroll:2018" }, { - "duration": "13.0", + "duration": "8.0", "name": "v8.browsing_desktop/browse:tech:discourse_infinite_scroll:2018" }, { - "duration": "19.0", + "duration": "14.0", "name": "v8.browsing_desktop/browse:tools:autocad:2021" }, { @@ -2712,27 +2588,27 @@ "name": "v8.browsing_desktop/browse:tools:docs_scrolling" }, { - "duration": "13.0", + "duration": "8.0", "name": "v8.browsing_desktop/browse:tools:gmail-compose:2020" }, { - "duration": "13.0", + "duration": "8.0", "name": "v8.browsing_desktop/browse:tools:gmail-labelclick:2020" }, { - "duration": "5.0", + "duration": "8.0", "name": "v8.browsing_desktop/browse:tools:gmail-openconversation:2020" }, { - "duration": "5.0", + "duration": "8.0", "name": "v8.browsing_desktop/browse:tools:gmail-search:2020" }, { - "duration": "12.0", + "duration": "11.0", "name": "v8.browsing_desktop/browse:tools:maps:2019" }, { - "duration": "25.0", + "duration": "26.0", "name": "v8.browsing_desktop/browse:tools:photoshop:2021" }, { @@ -2744,51 +2620,91 @@ "name": "v8.browsing_desktop/browse:tools:sheets:2019" }, { - "duration": "15.0", + "duration": "0.0", + "name": "wasmpspdfkit/https://pspdfkit.com/webassembly-benchmark/" + }, + { + "duration": "1.0", + "name": "webrtc/10s_datachannel_transfer" + }, + { + "duration": "12.0", "name": "webrtc/canvas_capture_peer_connection" }, { - "duration": "25.0", + "duration": "22.0", "name": "webrtc/codec_constraints_h264" }, { - "duration": "25.0", + "duration": "22.0", "name": "webrtc/codec_constraints_vp8" }, { - "duration": "25.0", + "duration": "22.0", "name": "webrtc/codec_constraints_vp9" }, { - "duration": "25.0", + "duration": "22.0", "name": "webrtc/encoded_insertable_streams" }, { - "duration": "15.0", + "duration": "12.0", "name": "webrtc/hd_local_stream_10s" }, { - "duration": "25.0", + "duration": "1.0", + "name": "webrtc/insertable_streams_audio_processing" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_camera_canvas2d_video" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_camera_noop_video" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_camera_webgl_pc" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_camera_webgl_video" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_pc_webgl_video" + }, + { + "duration": "1.0", + "name": "webrtc/insertable_streams_video_processing_video_webgl_video" + }, + { + "duration": "23.0", "name": "webrtc/multiple_peerconnections" }, { - "duration": "4.0", + "duration": "1.0", + "name": "webrtc/negotiate-timing" + }, + { + "duration": "1.0", "name": "webrtc/pause_play_peerconnections" }, { + "duration": "600.0", + "name": "dawn_perf_tests/_gtest_" + }, + { "duration": "7.0", "name": "views_perftests/_gtest_" }, { - "duration": "200.0", - "name": "base_perftests/_gtest_" - }, - { "duration": "125.0", "name": "components_perftests/_gtest_" }, { - "duration": "600.0", - "name": "dawn_perf_tests/_gtest_" + "duration": "200.0", + "name": "base_perftests/_gtest_" } ] \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/win-11-perf_map.json b/tools/perf/core/shard_maps/win-11-perf_map.json index 472cab0..406975a2 100644 --- a/tools/perf/core/shard_maps/win-11-perf_map.json +++ b/tools/perf/core/shard_maps/win-11-perf_map.json
@@ -5,25 +5,12 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 21, + "end": 13, "abridged": false }, "jetstream2": { "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -44,35 +31,19 @@ "1": { "benchmarks": { "blink_perf.accessibility": { - "begin": 21, + "begin": 13, "abridged": false }, "blink_perf.bindings": { "abridged": false }, "blink_perf.css": { - "abridged": false - }, - "blink_perf.dom": { - "end": 11, + "end": 19, "abridged": false }, "jetstream2": { "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -83,36 +54,23 @@ }, "2": { "benchmarks": { + "blink_perf.css": { + "begin": 19, + "abridged": false + }, "blink_perf.dom": { - "begin": 11, "abridged": false }, "blink_perf.events": { "abridged": false }, "blink_perf.image_decoder": { - "abridged": false - }, - "blink_perf.layout": { - "end": 108, + "end": 4, "abridged": false }, "jetstream2": { "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -123,45 +81,17 @@ }, "3": { "benchmarks": { + "blink_perf.image_decoder": { + "begin": 4, + "abridged": false + }, "blink_perf.layout": { - "begin": 108, - "abridged": false - }, - "blink_perf.owp_storage": { - "abridged": false - }, - "blink_perf.parser": { - "abridged": false - }, - "blink_perf.shadow_dom": { - "abridged": false - }, - "blink_perf.webaudio": { - "abridged": false - }, - "blink_perf.webcodecs": { - "abridged": false - }, - "blink_perf.webgl": { - "end": 3, + "end": 101, "abridged": false }, "jetstream2": { "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -172,8 +102,44 @@ }, "4": { "benchmarks": { + "blink_perf.layout": { + "begin": 101, + "abridged": false + }, + "blink_perf.owp_storage": { + "abridged": false + }, + "blink_perf.parser": { + "abridged": false + }, + "blink_perf.shadow_dom": { + "abridged": false + }, + "blink_perf.webaudio": { + "end": 8, + "abridged": false + }, + "jetstream2": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + } + }, + "5": { + "benchmarks": { + "blink_perf.webaudio": { + "begin": 8, + "abridged": false + }, + "blink_perf.webcodecs": { + "abridged": false + }, "blink_perf.webgl": { - "begin": 3, "abridged": false }, "blink_perf.webgl_fast_call": { @@ -185,22 +151,6 @@ "blink_perf.webgpu_fast_call": { "abridged": false }, - "jetstream2": { - "abridged": false - }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -224,7 +174,7 @@ } } }, - "5": { + "6": { "benchmarks": { "desktop_ui": { "abridged": false @@ -239,57 +189,7 @@ "abridged": false }, "media.desktop": { - "end": 18, - "abridged": false - }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - } - }, - "6": { - "benchmarks": { - "media.desktop": { - "begin": 18, - "abridged": false - }, - "memory.desktop": { - "abridged": false - }, - "octane": { - "abridged": false - }, - "power.desktop": { - "end": 3, - "abridged": false - }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], + "end": 11, "abridged": false }, "speedometer2": { @@ -302,28 +202,12 @@ }, "7": { "benchmarks": { - "power.desktop": { - "begin": 3, + "media.desktop": { + "begin": 11, "abridged": false }, - "rasterize_and_record_micro.top_25": { - "abridged": false - }, - "rendering.desktop": { - "end": 10, - "abridged": false - }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], + "memory.desktop": { + "end": 6, "abridged": false }, "speedometer2": { @@ -336,22 +220,15 @@ }, "8": { "benchmarks": { - "rendering.desktop": { - "begin": 10, - "end": 95, + "memory.desktop": { + "begin": 6, "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], + "octane": { + "abridged": false + }, + "power.desktop": { + "end": 10, "abridged": false }, "speedometer2": { @@ -364,51 +241,11 @@ }, "9": { "benchmarks": { - "rendering.desktop": { - "begin": 95, - "end": 181, + "power.desktop": { + "begin": 10, "abridged": false }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 43, - "end": 44 - }, - { - "begin": 72, - "end": 74 - } - ], - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - } - }, - "10": { - "benchmarks": { - "rendering.desktop": { - "begin": 181, - "end": 273, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - } - }, - "11": { - "benchmarks": { - "rendering.desktop": { - "begin": 273, + "rasterize_and_record_micro.top_25": { "abridged": false }, "rendering.desktop.notracing": { @@ -432,20 +269,47 @@ "speedometer3-future": { "abridged": false }, - "system_health.common_desktop": { - "end": 17, + "system_health.memory_desktop": { + "end": 1, + "abridged": false + } + } + }, + "10": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 1, + "end": 15, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + } + }, + "11": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 15, + "end": 26, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { "abridged": false } } }, "12": { "benchmarks": { - "system_health.common_desktop": { - "begin": 17, - "abridged": false - }, "system_health.memory_desktop": { - "end": 8, + "begin": 26, + "end": 48, "abridged": false }, "speedometer2": { @@ -459,8 +323,8 @@ "13": { "benchmarks": { "system_health.memory_desktop": { - "begin": 8, - "end": 23, + "begin": 48, + "end": 64, "abridged": false }, "speedometer2": { @@ -474,8 +338,8 @@ "14": { "benchmarks": { "system_health.memory_desktop": { - "begin": 23, - "end": 53, + "begin": 64, + "end": 66, "abridged": false }, "speedometer2": { @@ -489,8 +353,8 @@ "15": { "benchmarks": { "system_health.memory_desktop": { - "begin": 53, - "end": 65, + "begin": 66, + "end": 72, "abridged": false }, "speedometer2": { @@ -504,8 +368,11 @@ "16": { "benchmarks": { "system_health.memory_desktop": { - "begin": 65, - "end": 72, + "begin": 72, + "abridged": false + }, + "v8.browsing_desktop": { + "end": 1, "abridged": false }, "speedometer2": { @@ -518,12 +385,9 @@ }, "17": { "benchmarks": { - "system_health.memory_desktop": { - "begin": 72, - "abridged": false - }, "v8.browsing_desktop": { - "end": 10, + "begin": 1, + "end": 23, "abridged": false }, "speedometer2": { @@ -537,11 +401,11 @@ "18": { "benchmarks": { "v8.browsing_desktop": { - "begin": 10, + "begin": 23, "abridged": false }, "v8.browsing_desktop-future": { - "end": 6, + "end": 14, "abridged": false }, "speedometer2": { @@ -555,7 +419,7 @@ "19": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 6, + "begin": 14, "abridged": false }, "wasmpspdfkit": { @@ -581,30 +445,30 @@ } }, "extra_infos": { - "num_stories": 1166, - "predicted_min_shard_time": 830.0, - "predicted_min_shard_index": 15, - "predicted_max_shard_time": 1057.0, - "predicted_max_shard_index": 19, - "shard #0": 947.0, - "shard #1": 937.0, - "shard #2": 935.0, - "shard #3": 940.0, - "shard #4": 951.0, - "shard #5": 935.0, - "shard #6": 927.0, - "shard #7": 938.0, - "shard #8": 932.0, - "shard #9": 936.0, - "shard #10": 937.0, - "shard #11": 930.0, - "shard #12": 864.0, - "shard #13": 980.0, - "shard #14": 950.0, - "shard #15": 830.0, - "shard #16": 1013.0, - "shard #17": 943.0, - "shard #18": 951.0, - "shard #19": 1057.0 + "num_stories": 725, + "predicted_min_shard_time": 644.0, + "predicted_min_shard_index": 13, + "predicted_max_shard_time": 898.0, + "predicted_max_shard_index": 5, + "shard #0": 702.0, + "shard #1": 702.0, + "shard #2": 704.0, + "shard #3": 700.0, + "shard #4": 707.0, + "shard #5": 898.0, + "shard #6": 735.0, + "shard #7": 666.0, + "shard #8": 692.0, + "shard #9": 701.0, + "shard #10": 656.0, + "shard #11": 695.0, + "shard #12": 674.0, + "shard #13": 644.0, + "shard #14": 779.0, + "shard #15": 659.0, + "shard #16": 694.0, + "shard #17": 678.0, + "shard #18": 698.0, + "shard #19": 771.0 } } \ No newline at end of file
diff --git a/tools/perf/cross_device_test_config.py b/tools/perf/cross_device_test_config.py index f506fc1..76340f34 100644 --- a/tools/perf/cross_device_test_config.py +++ b/tools/perf/cross_device_test_config.py
@@ -128,10 +128,10 @@ 'speedometer': { 'http://browserbench.org/Speedometer/': 20, }, - 'speedometer2': { + 'speedometer2-nominorms': { 'Speedometer2': 20, }, - 'speedometer2-nominorms': { + 'speedometer2': { 'Speedometer2': 20, }, 'speedometer2-predictable': { @@ -179,12 +179,6 @@ 'jetstream2': { 'JetStream2': 5, }, - 'system_health.common_desktop': { - # cputimeToFirstContentfulPaint - 'browse:media:tumblr:2018': 10, - 'browse:social:tumblr_infinite_scroll:2018': 10, - 'load:search:google:2018': 10, - }, 'speedometer2': { 'Speedometer2': 20, },
diff --git a/tools/typescript/validate_tsconfig.py b/tools/typescript/validate_tsconfig.py index 3fb9026b..3de5b2c 100644 --- a/tools/typescript/validate_tsconfig.py +++ b/tools/typescript/validate_tsconfig.py
@@ -129,7 +129,6 @@ # TODO(b/315002705): Migrate shimless_rma to TypeScript and remove # exception. 'ash/webui/shimless_rma/', - 'ash/webui/shortcut_customization_ui/', # TODO(b/267329383): Migrate A11y to TypeScript. 'chrome/browser/resources/chromeos/accessibility', 'ui/file_manager/', @@ -160,7 +159,6 @@ 'chrome/test/data/webui/chromeos/shimless_rma', 'chrome/test/data/webui/cr_components/chromeos', 'chrome/test/data/webui/nearby_share', - 'chrome/test/data/webui/settings/chromeos', 'components/policy/resources/webui', 'ui/webui/resources/js', 'ui/webui/resources/mojo',
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc index d3afa56..bc4b730 100644 --- a/ui/base/clipboard/clipboard_android.cc +++ b/ui/base/clipboard/clipboard_android.cc
@@ -745,9 +745,8 @@ // background sequence. scoped_refptr<base::RefCountedMemory> image_memory = gfx::Image::CreateFrom1xBitmap(sk_bitmap).As1xPNGBytes(); - std::string packed(image_memory->front_as<char>(), image_memory->size()); - - g_map.Get().Set(ClipboardFormatType::PngType(), packed); + g_map.Get().Set(ClipboardFormatType::PngType(), + std::string(base::as_string_view(*image_memory))); } void ClipboardAndroid::WriteData(const ClipboardFormatType& format,
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc index 2db7579..7c1682f 100644 --- a/ui/base/clipboard/clipboard_ozone.cc +++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -217,11 +217,11 @@ auto it = offered_data_[buffer].find(mime_type); if (it == offered_data_[buffer].end()) return {}; - return base::make_span(it->second->front(), it->second->size()); + return base::span(it->second->as_vector()); } if (auto data = Read(buffer, mime_type)) - return base::make_span(data->front(), data->size()); + return base::span(data->as_vector()); return {}; }
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc index e023eda..341abf4f 100644 --- a/ui/base/resource/resource_bundle.cc +++ b/ui/base/resource/resource_bundle.cc
@@ -687,7 +687,7 @@ if (HasGzipHeader(data) || HasBrotliHeader(data)) { base::RefCountedString* bytes_string = new base::RefCountedString(); - DecompressIfNeeded(data, &(bytes_string->data())); + DecompressIfNeeded(data, &bytes_string->as_string()); return bytes_string; } @@ -1102,14 +1102,15 @@ if (!memory.get()) return false; - if (DecodePNG(memory->front(), memory->size(), bitmap, fell_back_to_1x)) + if (DecodePNG(memory->data(), memory->size(), bitmap, fell_back_to_1x)) { return true; + } #if !BUILDFLAG(IS_IOS) // iOS does not compile or use the JPEG codec. On other platforms, // 99% of our assets are PNGs, however fallback to JPEG. std::unique_ptr<SkBitmap> jpeg_bitmap( - gfx::JPEGCodec::Decode(memory->front(), memory->size())); + gfx::JPEGCodec::Decode(memory->data(), memory->size())); if (jpeg_bitmap.get()) { bitmap->swap(*jpeg_bitmap.get()); *fell_back_to_1x = false;
diff --git a/ui/base/resource/resource_bundle_unittest.cc b/ui/base/resource/resource_bundle_unittest.cc index 3d741eff..ec25fcd 100644 --- a/ui/base/resource/resource_bundle_unittest.cc +++ b/ui/base/resource/resource_bundle_unittest.cc
@@ -432,20 +432,17 @@ // Test normal uncompressed data. scoped_refptr<base::RefCountedMemory> resource = resource_bundle->LoadDataResourceBytes(4); - EXPECT_EQ("this is id 4", - std::string(resource->front_as<char>(), resource->size())); + EXPECT_EQ("this is id 4", base::as_string_view(*resource)); // Test the brotli data. scoped_refptr<base::RefCountedMemory> brotli_resource = resource_bundle->LoadDataResourceBytes(6); - EXPECT_EQ("this is id 6", std::string(brotli_resource->front_as<char>(), - brotli_resource->size())); + EXPECT_EQ("this is id 6", base::as_string_view(*brotli_resource)); // Test the gzipped data. scoped_refptr<base::RefCountedMemory> gzip_resource = resource_bundle->LoadDataResourceBytes(8); - EXPECT_EQ("this is id 8", std::string(gzip_resource->front_as<char>(), - gzip_resource->size())); + EXPECT_EQ("this is id 8", base::as_string_view(*gzip_resource)); } // Verify that we don't crash when trying to load a resource that is not found.
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc index a28adf70..df07e7c 100644 --- a/ui/base/x/selection_owner.cc +++ b/ui/base/x/selection_owner.cc
@@ -268,7 +268,7 @@ void SelectionOwner::ProcessIncrementalTransfer(IncrementalTransfer* transfer) { size_t remaining = transfer->data->size() - transfer->offset; size_t chunk_length = std::min(remaining, GetMaxIncrementalTransferSize()); - const uint8_t* data = transfer->data->front() + transfer->offset; + const uint8_t* data = transfer->data->data() + transfer->offset; std::vector<uint8_t> buf(data, data + chunk_length); connection_->SetArrayProperty(transfer->window, transfer->property, transfer->target, buf);
diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc index 09ddb2c..2a715df 100644 --- a/ui/base/x/selection_utils.cc +++ b/ui/base/x/selection_utils.cc
@@ -66,12 +66,7 @@ return std::string(); } - size_t size = memory->size(); - if (!size) - return std::string(); - - const unsigned char* front = memory->front(); - return std::string(reinterpret_cast<const char*>(front), size); + return std::string(base::as_string_view(*memory)); } std::u16string RefCountedMemoryToString16( @@ -81,12 +76,11 @@ return std::u16string(); } - size_t size = memory->size(); - if (!size) - return std::u16string(); - - const unsigned char* front = memory->front(); - return std::u16string(reinterpret_cast<const char16_t*>(front), size / 2); + auto in_bytes = base::span(*memory); + std::u16string out; + out.resize(memory->size() / 2u); + base::as_writable_byte_span(out).copy_from(in_bytes); + return out; } /////////////////////////////////////////////////////////////////////////////// @@ -164,7 +158,7 @@ } const unsigned char* SelectionData::GetData() const { - return memory_.get() ? memory_->front() : nullptr; + return memory_.get() ? memory_->data() : nullptr; } size_t SelectionData::GetSize() const {
diff --git a/ui/base/x/x11_cursor_loader.cc b/ui/base/x/x11_cursor_loader.cc index 1360840..8ee868fb 100644 --- a/ui/base/x/x11_cursor_loader.cc +++ b/ui/base/x/x11_cursor_loader.cc
@@ -386,7 +386,7 @@ .width = width, .height = height, .depth = 32, - .data = base::RefCountedBytes::TakeVector(&vec), + .data = base::MakeRefCounted<base::RefCountedBytes>(std::move(vec)), }; connection->PutImage(put_image_request);
diff --git a/ui/base/x/x11_display_util.cc b/ui/base/x/x11_display_util.cc index d44b518..ffaea4fe 100644 --- a/ui/base/x/x11_display_util.cc +++ b/ui/base/x/x11_display_util.cc
@@ -71,7 +71,7 @@ if (!response || response->format != 32 || response->value_len != 4) { return gfx::Rect(); } - const uint32_t* value = response->value->front_as<uint32_t>(); + const uint32_t* value = response->value->cast_to<uint32_t>(); return gfx::Rect(value[0], value[1], value[2], value[3]); } @@ -92,11 +92,11 @@ gfx::ICCProfile GetIccProfileSync(x11::Future<x11::GetPropertyReply> future) { auto response = future.Sync(); - if (!response || !response->value->size()) { + if (!response || !response->value_len) { return gfx::ICCProfile(); } - return gfx::ICCProfile::FromData(response->value->data(), - response->value->size()); + return gfx::ICCProfile::FromData(response->value->bytes(), + response->value_len * response->format / 8u); } x11::Future<x11::RandR::GetOutputPropertyReply> GetEdidFuture(
diff --git a/ui/base/x/x11_software_bitmap_presenter.cc b/ui/base/x/x11_software_bitmap_presenter.cc index 7ad8d08..0568940 100644 --- a/ui/base/x/x11_software_bitmap_presenter.cc +++ b/ui/base/x/x11_software_bitmap_presenter.cc
@@ -75,7 +75,7 @@ constexpr auto kAllPlanes = std::numeric_limits<decltype(x11::GetImageRequest::plane_mask)>::max(); - scoped_refptr<base::RefCountedMemory> bg; + scoped_refptr<x11::UnsizedRefCountedMemory> bg; auto req = connection->GetImage({x11::ImageFormat::ZPixmap, widget, x_i16, y_i16, w_u16, h_u16, kAllPlanes}); if (auto reply = req.Sync()) { @@ -103,8 +103,8 @@ SkBitmap bg_bitmap; SkImageInfo image_info = SkImageInfo::Make( - width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType); - if (!bg_bitmap.installPixels(image_info, const_cast<uint8_t*>(bg->data()), + w_u16, h_u16, kBGRA_8888_SkColorType, kPremul_SkAlphaType); + if (!bg_bitmap.installPixels(image_info, bg->bytes(), image_info.minRowBytes())) { return false; } @@ -119,8 +119,9 @@ } canvas.drawImage(fg_bitmap.asImage(), 0, 0); - connection->PutImage({x11::ImageFormat::ZPixmap, widget, gc, w_u16, h_u16, - x_i16, y_i16, 0, d_u8, bg}); + connection->PutImage( + {x11::ImageFormat::ZPixmap, widget, gc, w_u16, h_u16, x_i16, y_i16, 0, + d_u8, x11::SizedRefCountedMemory::From(bg, size_t{w_u16} * h_u16)}); return true; }
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc index 5f17a92..b428665 100644 --- a/ui/base/x/x11_util.cc +++ b/ui/base/x/x11_util.cc
@@ -294,7 +294,11 @@ if (!response || !response->format) { return false; } - *out_data = response->value; + // SAFETY: The GetProperty response has a `format` which specified the number + // of bits per object in the `value` and `value_len` for the number of + // objects, so `value_len * format / 8` gives the number of bytes in `value`. + *out_data = UNSAFE_BUFFERS(x11::SizedRefCountedMemory::From( + response->value, response->value_len * response->format / 8u)); if (out_type) { *out_type = response->type; }
diff --git a/ui/base/x/x11_workspace_handler.cc b/ui/base/x/x11_workspace_handler.cc index 6916705b8..ad59d0a 100644 --- a/ui/base/x/x11_workspace_handler.cc +++ b/ui/base/x/x11_workspace_handler.cc
@@ -58,14 +58,14 @@ void X11WorkspaceHandler::OnWorkspaceResponse( x11::GetPropertyResponse response) { - if (!response || response->format != 32 || response->value->size() < 4) { + if (!response || response->format != 32 || response->value_len < 1) { return; } DCHECK_EQ(response->bytes_after, 0U); DCHECK_EQ(response->type, static_cast<x11::Atom>(x11::Atom::CARDINAL)); uint32_t workspace; - memcpy(&workspace, response->value->data(), 4); + memcpy(&workspace, response->value->bytes(), 4); workspace_ = base::NumberToString(workspace); delegate_->OnCurrentWorkspaceChanged(workspace_); }
diff --git a/ui/events/ash/event_rewriter_ash.cc b/ui/events/ash/event_rewriter_ash.cc index 6ab8958..9fe1bb95 100644 --- a/ui/events/ash/event_rewriter_ash.cc +++ b/ui/events/ash/event_rewriter_ash.cc
@@ -688,6 +688,7 @@ } } +// TODO(dpad, b/329330990): Update to support FN key in this metric. void RecordRewritingToFunctionKeys( const KeyEvent& key_event, const EventRewriterAsh::MutableKeyState* rewritten_state) { @@ -1872,131 +1873,36 @@ KeyboardCapability::KeyboardTopRowLayout layout = keyboard_capability_->GetTopRowLayout(device_id); - const bool search_is_pressed = (state->flags & EF_COMMAND_DOWN) != 0; - const bool flip_remapping = + // The modifier to base rewriting on depends on if the keyboard uses an FN key + // or not. + const EventFlags flip_rewrite_modifier = + keyboard_capability_->HasFunctionKey(device_id) ? EF_FUNCTION_DOWN + : EF_COMMAND_DOWN; + const bool flip_modifier_is_pressed = + (state->flags & flip_rewrite_modifier) != 0; + const bool should_flip_top_row_mapping = ShouldRewriteMetaTopRowKeyComboEvents(delegate_, device_id) && - search_is_pressed; + flip_modifier_is_pressed; if (layout == KeyboardCapability::KeyboardTopRowLayout::kKbdTopRowLayoutCustom) { if (RewriteTopRowKeysForCustomLayout(key_event, device_id, - search_is_pressed, state)) { + should_flip_top_row_mapping, + flip_rewrite_modifier, state)) { return; } } else if (layout == KeyboardCapability::KeyboardTopRowLayout:: kKbdTopRowLayoutWilco || layout == KeyboardCapability::KeyboardTopRowLayout:: kKbdTopRowLayoutDrallion) { - if (RewriteTopRowKeysForLayoutWilco(key_event, device_id, search_is_pressed, - state, layout)) { + if (RewriteTopRowKeysForLayoutWilco(key_event, device_id, + should_flip_top_row_mapping, + flip_rewrite_modifier, state, layout)) { return; } - } else if ((state->key_code >= VKEY_F1) && (state->key_code <= VKEY_F12)) { - // Search? Top Row Rewrite Meta F-Key Result - // ------- -------- ------------------ ------ - // No Fn Yes Unchanged - // No System Yes Fn -> System - // Yes Fn Yes Fn -> System - // Yes System Yes Search+Fn -> Fn - // No Fn No Unchanged - // No System No Fn -> System - // Yes Fn No Unchanged - // Yes System No Unchanged - if (ForceTopRowAsFunctionKeys(device_id) == flip_remapping) { - // Rewrite the F1-F12 keys on a Chromebook keyboard to system keys. - // This is the original Chrome OS layout. - static const KeyboardRemapping kFkeysToSystemKeys1[] = { - {{EF_NONE, VKEY_F1}, - {EF_NONE, DomCode::BROWSER_BACK, DomKey::BROWSER_BACK, - VKEY_BROWSER_BACK}}, - {{EF_NONE, VKEY_F2}, - {EF_NONE, DomCode::BROWSER_FORWARD, DomKey::BROWSER_FORWARD, - VKEY_BROWSER_FORWARD}}, - {{EF_NONE, VKEY_F3}, - {EF_NONE, DomCode::BROWSER_REFRESH, DomKey::BROWSER_REFRESH, - VKEY_BROWSER_REFRESH}}, - {{EF_NONE, VKEY_F4}, - {EF_NONE, DomCode::ZOOM_TOGGLE, DomKey::ZOOM_TOGGLE, VKEY_ZOOM}}, - {{EF_NONE, VKEY_F5}, - {EF_NONE, DomCode::SELECT_TASK, DomKey::LAUNCH_MY_COMPUTER, - VKEY_MEDIA_LAUNCH_APP1}}, - {{EF_NONE, VKEY_F6}, - {EF_NONE, DomCode::BRIGHTNESS_DOWN, DomKey::BRIGHTNESS_DOWN, - VKEY_BRIGHTNESS_DOWN}}, - {{EF_NONE, VKEY_F7}, - {EF_NONE, DomCode::BRIGHTNESS_UP, DomKey::BRIGHTNESS_UP, - VKEY_BRIGHTNESS_UP}}, - {{EF_NONE, VKEY_F8}, - {EF_NONE, DomCode::VOLUME_MUTE, DomKey::AUDIO_VOLUME_MUTE, - VKEY_VOLUME_MUTE}}, - {{EF_NONE, VKEY_F9}, - {EF_NONE, DomCode::VOLUME_DOWN, DomKey::AUDIO_VOLUME_DOWN, - VKEY_VOLUME_DOWN}}, - {{EF_NONE, VKEY_F10}, - {EF_NONE, DomCode::VOLUME_UP, DomKey::AUDIO_VOLUME_UP, - VKEY_VOLUME_UP}}, - }; - // The new layout with forward button removed and play/pause added. - static const KeyboardRemapping kFkeysToSystemKeys2[] = { - {{EF_NONE, VKEY_F1}, - {EF_NONE, DomCode::BROWSER_BACK, DomKey::BROWSER_BACK, - VKEY_BROWSER_BACK}}, - {{EF_NONE, VKEY_F2}, - {EF_NONE, DomCode::BROWSER_REFRESH, DomKey::BROWSER_REFRESH, - VKEY_BROWSER_REFRESH}}, - {{EF_NONE, VKEY_F3}, - {EF_NONE, DomCode::ZOOM_TOGGLE, DomKey::ZOOM_TOGGLE, VKEY_ZOOM}}, - {{EF_NONE, VKEY_F4}, - {EF_NONE, DomCode::SELECT_TASK, DomKey::LAUNCH_MY_COMPUTER, - VKEY_MEDIA_LAUNCH_APP1}}, - {{EF_NONE, VKEY_F5}, - {EF_NONE, DomCode::BRIGHTNESS_DOWN, DomKey::BRIGHTNESS_DOWN, - VKEY_BRIGHTNESS_DOWN}}, - {{EF_NONE, VKEY_F6}, - {EF_NONE, DomCode::BRIGHTNESS_UP, DomKey::BRIGHTNESS_UP, - VKEY_BRIGHTNESS_UP}}, - {{EF_NONE, VKEY_F7}, - {EF_NONE, DomCode::MEDIA_PLAY_PAUSE, DomKey::MEDIA_PLAY_PAUSE, - VKEY_MEDIA_PLAY_PAUSE}}, - {{EF_NONE, VKEY_F8}, - {EF_NONE, DomCode::VOLUME_MUTE, DomKey::AUDIO_VOLUME_MUTE, - VKEY_VOLUME_MUTE}}, - {{EF_NONE, VKEY_F9}, - {EF_NONE, DomCode::VOLUME_DOWN, DomKey::AUDIO_VOLUME_DOWN, - VKEY_VOLUME_DOWN}}, - {{EF_NONE, VKEY_F10}, - {EF_NONE, DomCode::VOLUME_UP, DomKey::AUDIO_VOLUME_UP, - VKEY_VOLUME_UP}}, - }; - - const KeyboardRemapping* mapping = nullptr; - size_t mappingSize = 0u; - switch (layout) { - case KeyboardCapability::KeyboardTopRowLayout::kKbdTopRowLayout2: - mapping = kFkeysToSystemKeys2; - mappingSize = std::size(kFkeysToSystemKeys2); - break; - case KeyboardCapability::KeyboardTopRowLayout::kKbdTopRowLayout1: - default: - mapping = kFkeysToSystemKeys1; - mappingSize = std::size(kFkeysToSystemKeys1); - break; - } - - MutableKeyState incoming_without_command = *state; - incoming_without_command.flags &= ~EF_COMMAND_DOWN; - if (RewriteWithKeyboardRemappings(mapping, mappingSize, - incoming_without_command, state)) { - // If the remapping was not supposed to be flipped and search is - // pressed, the search flag must be added back. - if (!flip_remapping && search_is_pressed) { - state->flags |= EF_COMMAND_DOWN; - } - return; - } - } else if (flip_remapping) { - // If we were supposed to flip the remapping, that means we should remove - // the search flag. - state->flags &= ~EF_COMMAND_DOWN; + } else { + if (RewriteTopRowKeysForStandardLayouts( + key_event, device_id, should_flip_top_row_mapping, + flip_rewrite_modifier, flip_modifier_is_pressed, state, layout)) { return; } } @@ -2316,17 +2222,14 @@ bool EventRewriterAsh::RewriteTopRowKeysForCustomLayout( const KeyEvent& key_event, int device_id, - bool search_is_pressed, + bool should_flip_top_row_mapping, + EventFlags flip_rewrite_modifier, EventRewriterAsh::MutableKeyState* state) { // Incoming function keys are never remapped. if (IsCustomLayoutFunctionKey(key_event.key_code())) { return true; } - const bool flip_remapping = - ShouldRewriteMetaTopRowKeyComboEvents(delegate_, device_id) && - search_is_pressed; - const auto* scan_code_vector_ptr = keyboard_capability_->GetTopRowScanCodes(device_id); if (!scan_code_vector_ptr || scan_code_vector_ptr->empty()) { @@ -2341,7 +2244,7 @@ // If the scan code appears in the top row mapping it is an action key. const bool is_action_key = (key_iter != scan_code_vector.end()); if (is_action_key) { - if (flip_remapping != ForceTopRowAsFunctionKeys(device_id)) { + if (should_flip_top_row_mapping != ForceTopRowAsFunctionKeys(device_id)) { ApplyRemapping(kCustomTopRowLayoutFKeys[std::distance( scan_code_vector.begin(), key_iter)], state); @@ -2349,8 +2252,8 @@ // Clear command/search key if pressed and we were supposed to perform a // remapping. - if (flip_remapping) { - state->flags &= ~EF_COMMAND_DOWN; + if (should_flip_top_row_mapping) { + state->flags &= ~flip_rewrite_modifier; } return true; @@ -2386,7 +2289,8 @@ bool EventRewriterAsh::RewriteTopRowKeysForLayoutWilco( const KeyEvent& key_event, int device_id, - bool search_is_pressed, + bool should_flip_top_row_mapping, + EventFlags flip_rewrite_modifier, MutableKeyState* state, KeyboardCapability::KeyboardTopRowLayout layout) { // When the kernel issues an function key (Fn modifier help down) and the @@ -2460,18 +2364,16 @@ {{EF_NONE, VKEY_PRIVACY_SCREEN_TOGGLE}, {EF_NONE, DomCode::F12, DomKey::F12, VKEY_F12}}, }; - const bool flip_remapping = - ShouldRewriteMetaTopRowKeyComboEvents(delegate_, device_id) && - search_is_pressed; - MutableKeyState incoming_with_command_removed_if_neccessary = *state; - if (flip_remapping) { - incoming_with_command_removed_if_neccessary.flags &= ~EF_COMMAND_DOWN; + MutableKeyState incoming_with_modifier_removed_if_neccessary = *state; + if (should_flip_top_row_mapping) { + incoming_with_modifier_removed_if_neccessary.flags &= + ~flip_rewrite_modifier; } if ((state->key_code >= VKEY_F1) && (state->key_code <= VKEY_F12)) { // Incoming key code is a Fn key. Check if it needs to be mapped back to its // corresponding action key. - if (flip_remapping) { + if (should_flip_top_row_mapping) { // On some Drallion devices, F12 shares a key with privacy screen toggle. // Account for this before rewriting for Wilco 1.0 layout. if (layout == KeyboardCapability::KeyboardTopRowLayout:: @@ -2482,33 +2384,33 @@ state->code = DomCode::PRIVACY_SCREEN_TOGGLE; } // Clear command flag if the remapping should be flipped. - state->flags = (state->flags & ~EF_COMMAND_DOWN); + state->flags = (state->flags & ~flip_rewrite_modifier); return true; } return RewriteWithKeyboardRemappings( kFnkeysToActionKeys, std::size(kFnkeysToActionKeys), - incoming_with_command_removed_if_neccessary, state); + incoming_with_modifier_removed_if_neccessary, state); } return true; } else if (IsKeyCodeInMappings(state->key_code, kActionToFnKeys, std::size(kActionToFnKeys))) { // Incoming key code is an action key. Check if it needs to be mapped back // to its corresponding function key. - if (flip_remapping != ForceTopRowAsFunctionKeys(device_id)) { + if (should_flip_top_row_mapping != ForceTopRowAsFunctionKeys(device_id)) { // On Drallion, mirror mode toggle is on its own key so don't remap it. if (layout == KeyboardCapability::KeyboardTopRowLayout:: kKbdTopRowLayoutDrallion && MatchKeyboardRemapping(*state, {EF_CONTROL_DOWN, VKEY_ZOOM})) { // Clear command flag before returning if the remapping should be // flipped. - if (flip_remapping) { - state->flags = (state->flags & ~EF_COMMAND_DOWN); + if (should_flip_top_row_mapping) { + state->flags = (state->flags & ~flip_rewrite_modifier); } return true; } return RewriteWithKeyboardRemappings( kActionToFnKeys, std::size(kActionToFnKeys), - incoming_with_command_removed_if_neccessary, state); + incoming_with_modifier_removed_if_neccessary, state); } // Remap Privacy Screen Toggle to F12 on Drallion devices that do not have // privacy screens. @@ -2522,8 +2424,8 @@ } // If the mapping should be flipped when command is down, the flag needs to // be cleared. - if (flip_remapping) { - state->flags &= ~EF_COMMAND_DOWN; + if (should_flip_top_row_mapping) { + state->flags &= ~flip_rewrite_modifier; } return true; } @@ -2531,6 +2433,135 @@ return false; } +bool EventRewriterAsh::RewriteTopRowKeysForStandardLayouts( + const KeyEvent& key_event, + int device_id, + bool should_flip_top_row_mapping, + EventFlags flip_rewrite_modifier, + bool rewrite_modifier_is_pressed, + MutableKeyState* state, + KeyboardCapability::KeyboardTopRowLayout layout) { + // Rewrite the F1-F12 keys on a Chromebook keyboard to system keys. + // This is the original Chrome OS layout. + static const KeyboardRemapping kFkeysToSystemKeys1[] = { + {{EF_NONE, VKEY_F1}, + {EF_NONE, DomCode::BROWSER_BACK, DomKey::BROWSER_BACK, + VKEY_BROWSER_BACK}}, + {{EF_NONE, VKEY_F2}, + {EF_NONE, DomCode::BROWSER_FORWARD, DomKey::BROWSER_FORWARD, + VKEY_BROWSER_FORWARD}}, + {{EF_NONE, VKEY_F3}, + {EF_NONE, DomCode::BROWSER_REFRESH, DomKey::BROWSER_REFRESH, + VKEY_BROWSER_REFRESH}}, + {{EF_NONE, VKEY_F4}, + {EF_NONE, DomCode::ZOOM_TOGGLE, DomKey::ZOOM_TOGGLE, VKEY_ZOOM}}, + {{EF_NONE, VKEY_F5}, + {EF_NONE, DomCode::SELECT_TASK, DomKey::LAUNCH_MY_COMPUTER, + VKEY_MEDIA_LAUNCH_APP1}}, + {{EF_NONE, VKEY_F6}, + {EF_NONE, DomCode::BRIGHTNESS_DOWN, DomKey::BRIGHTNESS_DOWN, + VKEY_BRIGHTNESS_DOWN}}, + {{EF_NONE, VKEY_F7}, + {EF_NONE, DomCode::BRIGHTNESS_UP, DomKey::BRIGHTNESS_UP, + VKEY_BRIGHTNESS_UP}}, + {{EF_NONE, VKEY_F8}, + {EF_NONE, DomCode::VOLUME_MUTE, DomKey::AUDIO_VOLUME_MUTE, + VKEY_VOLUME_MUTE}}, + {{EF_NONE, VKEY_F9}, + {EF_NONE, DomCode::VOLUME_DOWN, DomKey::AUDIO_VOLUME_DOWN, + VKEY_VOLUME_DOWN}}, + {{EF_NONE, VKEY_F10}, + {EF_NONE, DomCode::VOLUME_UP, DomKey::AUDIO_VOLUME_UP, VKEY_VOLUME_UP}}, + }; + + // The new layout with forward button removed and play/pause added. + static const KeyboardRemapping kFkeysToSystemKeys2[] = { + {{EF_NONE, VKEY_F1}, + {EF_NONE, DomCode::BROWSER_BACK, DomKey::BROWSER_BACK, + VKEY_BROWSER_BACK}}, + {{EF_NONE, VKEY_F2}, + {EF_NONE, DomCode::BROWSER_REFRESH, DomKey::BROWSER_REFRESH, + VKEY_BROWSER_REFRESH}}, + {{EF_NONE, VKEY_F3}, + {EF_NONE, DomCode::ZOOM_TOGGLE, DomKey::ZOOM_TOGGLE, VKEY_ZOOM}}, + {{EF_NONE, VKEY_F4}, + {EF_NONE, DomCode::SELECT_TASK, DomKey::LAUNCH_MY_COMPUTER, + VKEY_MEDIA_LAUNCH_APP1}}, + {{EF_NONE, VKEY_F5}, + {EF_NONE, DomCode::BRIGHTNESS_DOWN, DomKey::BRIGHTNESS_DOWN, + VKEY_BRIGHTNESS_DOWN}}, + {{EF_NONE, VKEY_F6}, + {EF_NONE, DomCode::BRIGHTNESS_UP, DomKey::BRIGHTNESS_UP, + VKEY_BRIGHTNESS_UP}}, + {{EF_NONE, VKEY_F7}, + {EF_NONE, DomCode::MEDIA_PLAY_PAUSE, DomKey::MEDIA_PLAY_PAUSE, + VKEY_MEDIA_PLAY_PAUSE}}, + {{EF_NONE, VKEY_F8}, + {EF_NONE, DomCode::VOLUME_MUTE, DomKey::AUDIO_VOLUME_MUTE, + VKEY_VOLUME_MUTE}}, + {{EF_NONE, VKEY_F9}, + {EF_NONE, DomCode::VOLUME_DOWN, DomKey::AUDIO_VOLUME_DOWN, + VKEY_VOLUME_DOWN}}, + {{EF_NONE, VKEY_F10}, + {EF_NONE, DomCode::VOLUME_UP, DomKey::AUDIO_VOLUME_UP, VKEY_VOLUME_UP}}, + }; + + if ((state->key_code < VKEY_F1) || (state->key_code > VKEY_F12)) { + return false; + } + + // F Keys should be rewritten to action keys if "top row are function keys" is + // disabled and we shouldn't flip the default due to a modifier key OR if "top + // row are function keys" is enabled and we should flip the default due to a + // modifier key. + // Search? Top Row Rewrite Meta F-Key Result + // ------- -------- ------------------ ------ + // No Fn Yes Unchanged + // No System Yes Fn -> System + // Yes Fn Yes Fn -> System + // Yes System Yes Search+Fn -> Fn + // No Fn No Unchanged + // No System No Fn -> System + // Yes Fn No Unchanged + // Yes System No Unchanged + const bool should_rewrite_to_action_keys = + (ForceTopRowAsFunctionKeys(device_id) == should_flip_top_row_mapping); + if (should_rewrite_to_action_keys) { + const KeyboardRemapping* mapping = nullptr; + size_t mappingSize = 0u; + switch (layout) { + case KeyboardCapability::KeyboardTopRowLayout::kKbdTopRowLayout2: + mapping = kFkeysToSystemKeys2; + mappingSize = std::size(kFkeysToSystemKeys2); + break; + case KeyboardCapability::KeyboardTopRowLayout::kKbdTopRowLayout1: + default: + mapping = kFkeysToSystemKeys1; + mappingSize = std::size(kFkeysToSystemKeys1); + break; + } + + MutableKeyState incoming_without_flip_modifier = *state; + incoming_without_flip_modifier.flags &= ~flip_rewrite_modifier; + if (RewriteWithKeyboardRemappings(mapping, mappingSize, + incoming_without_flip_modifier, state)) { + // If the remapping was not supposed to be flipped and search is + // pressed, the search flag must be added back. + if (!should_flip_top_row_mapping && rewrite_modifier_is_pressed) { + state->flags |= flip_rewrite_modifier; + } + return true; + } + } else if (should_flip_top_row_mapping) { + // If we were supposed to flip the remapping, that means we should remove + // the search flag. + state->flags &= ~flip_rewrite_modifier; + return true; + } + + return false; +} + bool EventRewriterAsh::ForceTopRowAsFunctionKeys(int device_id) const { return delegate_ && delegate_->TopRowKeysAreFunctionKeys(device_id); }
diff --git a/ui/events/ash/event_rewriter_ash.h b/ui/events/ash/event_rewriter_ash.h index 85ccf25..89029e8 100644 --- a/ui/events/ash/event_rewriter_ash.h +++ b/ui/events/ash/event_rewriter_ash.h
@@ -332,14 +332,25 @@ // support supplying a custom layout via sysfs. bool RewriteTopRowKeysForCustomLayout(const ui::KeyEvent& key_event, int device_id, - bool search_is_pressed, + bool flip_remapping, + EventFlags flip_remapping_flag, MutableKeyState* state); // Handle Fn/Action key remapping for Wilco keyboard layout. bool RewriteTopRowKeysForLayoutWilco( const KeyEvent& key_event, int device_id, - bool search_is_pressed, + bool flip_remapping, + EventFlags flip_remapping_flag, + MutableKeyState* state, + KeyboardCapability::KeyboardTopRowLayout layout); + + bool RewriteTopRowKeysForStandardLayouts( + const KeyEvent& key_event, + int device_id, + bool flip_remapping, + EventFlags flip_remapping_flag, + bool rewrite_modifier_is_pressed, MutableKeyState* state, KeyboardCapability::KeyboardTopRowLayout layout);
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc index dfd0fe9..8c4b88a 100644 --- a/ui/events/platform/x11/x11_event_source.cc +++ b/ui/events/platform/x11/x11_event_source.cc
@@ -10,6 +10,7 @@ #include "base/memory/free_deleter.h" #include "base/memory/ref_counted_memory.h" #include "base/metrics/histogram_macros.h" +#include "base/numerics/safe_conversions.h" #include "base/ranges/algorithm.h" #include "build/chromeos_buildflags.h" #include "ui/events/devices/x11/device_data_manager_x11.h" @@ -203,14 +204,14 @@ } // Make a no-op property change on |dummy_window_|. - std::vector<uint8_t> data{0}; + std::vector<uint8_t> data({0}); connection_->ChangeProperty(x11::ChangePropertyRequest{ .window = static_cast<x11::Window>(dummy_window_), .property = dummy_atom_, .type = x11::Atom::STRING, .format = CHAR_BIT, - .data_len = 1, - .data = base::RefCountedBytes::TakeVector(&data), + .data_len = base::checked_cast<uint32_t>(data.size()), + .data = base::MakeRefCounted<base::RefCountedBytes>(std::move(data)), }); // Observe the resulting PropertyNotify event to obtain the timestamp.
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc index 51ff8d6f..42c079d1 100644 --- a/ui/gfx/image/image.cc +++ b/ui/gfx/image/image.cc
@@ -219,7 +219,7 @@ return Image(); scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes()); - raw_data->data().assign(input, input + input_size); + raw_data->as_vector().assign(input, input + input_size); return CreateFrom1xPNGBytes(raw_data); }
diff --git a/ui/gfx/image/image_generic.cc b/ui/gfx/image/image_generic.cc index 5d4940e..3222846 100644 --- a/ui/gfx/image/image_generic.cc +++ b/ui/gfx/image/image_generic.cc
@@ -74,7 +74,7 @@ scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data; CHECK(raw_data.get()); SkBitmap bitmap; - if (!PNGCodec::Decode(raw_data->front(), raw_data->size(), &bitmap)) { + if (!PNGCodec::Decode(raw_data->data(), raw_data->size(), &bitmap)) { LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << "."; return ImageSkiaRep(); } @@ -118,7 +118,7 @@ scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes()); if (image_skia_rep.scale() != 1.0f || !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.GetBitmap(), false, - &png_bytes->data())) { + &png_bytes->as_vector())) { return nullptr; } return png_bytes;
diff --git a/ui/gfx/image/image_ios.mm b/ui/gfx/image/image_ios.mm index 9fdd132..b717aee 100644 --- a/ui/gfx/image/image_ios.mm +++ b/ui/gfx/image/image_ios.mm
@@ -109,8 +109,8 @@ scoped_refptr<base::RefCountedBytes> png_bytes( new base::RefCountedBytes()); - png_bytes->data().resize(data.length); - [data getBytes:&png_bytes->data().at(0) length:data.length]; + png_bytes->as_vector().resize(data.length); + [data getBytes:&png_bytes->as_vector().at(0) length:data.length]; return png_bytes; }
diff --git a/ui/gfx/image/image_mac.mm b/ui/gfx/image/image_mac.mm index 1b0f60f..a05b0d51 100644 --- a/ui/gfx/image/image_mac.mm +++ b/ui/gfx/image/image_mac.mm
@@ -90,10 +90,10 @@ [[NSBitmapImageRep alloc] initWithCGImage:cg_image]; NSData* ns_data = [ns_bitmap representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; - const unsigned char* bytes = static_cast<const unsigned char*>(ns_data.bytes); + auto* bytes = static_cast<const uint8_t*>(ns_data.bytes); scoped_refptr<base::RefCountedBytes> refcounted_bytes( new base::RefCountedBytes()); - refcounted_bytes->data().assign(bytes, bytes + ns_data.length); + refcounted_bytes->as_vector().assign(bytes, bytes + ns_data.length); return refcounted_bytes; }
diff --git a/ui/gfx/image/image_png_rep.cc b/ui/gfx/image/image_png_rep.cc index 332d35ed..9ea4bcd 100644 --- a/ui/gfx/image/image_png_rep.cc +++ b/ui/gfx/image/image_png_rep.cc
@@ -29,8 +29,7 @@ // using the gfx::PNGCodec API, is to decode the whole thing. CHECK(raw_data.get()); SkBitmap bitmap; - if (!gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(), - &bitmap)) { + if (!gfx::PNGCodec::Decode(raw_data->data(), raw_data->size(), &bitmap)) { LOG(ERROR) << "Unable to decode PNG."; return gfx::Size(0, 0); }
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc index d833500..8921398ac 100644 --- a/ui/gfx/image/image_unittest.cc +++ b/ui/gfx/image/image_unittest.cc
@@ -402,7 +402,7 @@ TEST_F(ImageTest, PNGDecodeToSkiaFailure) { scoped_refptr<base::RefCountedBytes> invalid_bytes( new base::RefCountedBytes()); - invalid_bytes->data().push_back('0'); + invalid_bytes->as_vector().push_back('0'); std::vector<gfx::ImagePNGRep> image_png_reps; image_png_reps.push_back(gfx::ImagePNGRep( invalid_bytes, 1.0f)); @@ -413,7 +413,7 @@ TEST_F(ImageTest, PNGDecodeToPlatformFailure) { scoped_refptr<base::RefCountedBytes> invalid_bytes( new base::RefCountedBytes()); - invalid_bytes->data().push_back('0'); + invalid_bytes->as_vector().push_back('0'); std::vector<gfx::ImagePNGRep> image_png_reps; image_png_reps.push_back(gfx::ImagePNGRep( invalid_bytes, 1.0f));
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc index 1cc4665..a5051e85 100644 --- a/ui/gfx/image/image_unittest_util.cc +++ b/ui/gfx/image/image_unittest_util.cc
@@ -66,7 +66,7 @@ SkColor color) { SkBitmap bitmap = CreateBitmap(edge_size, edge_size, color); scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes()); - PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->data()); + PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->as_vector()); return bytes; }
diff --git a/ui/gfx/x/connection.cc b/ui/gfx/x/connection.cc index 2c32f6a..62b8cc6 100644 --- a/ui/gfx/x/connection.cc +++ b/ui/gfx/x/connection.cc
@@ -73,7 +73,7 @@ // Errors are always a fixed 32 bytes. for (size_t i = 0; i < 32; i++) { char buf[3]; - sprintf(buf, "%02x", error_bytes_->data()[i]); + sprintf(buf, "%02x", error_bytes_->bytes()[i]); ss << "0x" << buf; if (i != 31) { ss << ", "; @@ -131,9 +131,12 @@ window_event_manager_(this) { CHECK(connection_); if (Ready()) { - auto buf = ReadBuffer(base::MakeRefCounted<UnretainedRefCountedMemory>( - xcb_get_setup(XcbConnection())), - true); + auto buf = ReadBuffer( + base::MakeRefCounted<UnretainedRefCountedMemory>( + // ReadBuffer doesn't use write access but we don't have a const + // UnsizedRefCountedMemory type for ReadBuffer to use. + const_cast<xcb_setup_t*>(xcb_get_setup(XcbConnection()))), + true); setup_ = Read<Setup>(&buf); default_screen_ = &setup_.roots[DefaultScreenId()]; InitRootDepthAndVisual(); @@ -658,6 +661,21 @@ } } +Future<void> Connection::SetArrayPropertyImpl( + Window window, + Atom name, + Atom type, + uint8_t format, + base::span<const uint8_t> values) { + return ChangeProperty(ChangePropertyRequest{ + .window = static_cast<Window>(window), + .property = name, + .type = type, + .format = format, + .data_len = static_cast<uint32_t>(values.size()) / (format / 8u), + .data = base::MakeRefCounted<base::RefCountedBytes>(values)}); +} + std::unique_ptr<FutureImpl> Connection::SendRequestImpl( WriteBuffer* buf, const char* request_name_for_tracing, @@ -682,10 +700,9 @@ }; static_assert(sizeof(ExtendedRequestHeader) == 8, ""); - auto& first_buffer = buf->GetBuffers()[0]; - CHECK_GE(first_buffer->size(), sizeof(RequestHeader)); - auto* old_header = reinterpret_cast<RequestHeader*>( - const_cast<uint8_t*>(first_buffer->data())); + base::span<uint8_t> first_buffer = buf->GetBuffers()[0]; + CHECK_GE(first_buffer.size(), sizeof(RequestHeader)); + auto* old_header = reinterpret_cast<RequestHeader*>(first_buffer.data()); ExtendedRequestHeader new_header{*old_header, 0}; // Requests are always a multiple of 4 bytes on the wire. Because of this, @@ -704,16 +721,14 @@ new_header.long_length = size32 + 1; io.push_back({&new_header, sizeof(ExtendedRequestHeader)}); - first_buffer = base::MakeRefCounted<OffsetRefCountedMemory>( - first_buffer, sizeof(RequestHeader), - first_buffer->size() - sizeof(RequestHeader)); + buf->OffsetFirstBuffer(sizeof(RequestHeader)); } else { LOG(ERROR) << "Cannot send request of length " << buf->offset(); return nullptr; } - for (auto& buffer : buf->GetBuffers()) { - io.push_back({const_cast<uint8_t*>(buffer->data()), buffer->size()}); + for (base::span<uint8_t> buffer : buf->GetBuffers()) { + io.push_back({buffer.data(), buffer.size()}); } xpr.count = io.size() - 2; @@ -898,7 +913,7 @@ uint8_t error_code; uint16_t sequence; }; - auto error_code = error_bytes->front_as<ErrorHeader>()->error_code; + auto error_code = error_bytes->cast_to<ErrorHeader>()->error_code; if (auto parser = error_parsers_[error_code]) { return parser(error_bytes); }
diff --git a/ui/gfx/x/connection.h b/ui/gfx/x/connection.h index 1866edfe..77601c8 100644 --- a/ui/gfx/x/connection.h +++ b/ui/gfx/x/connection.h
@@ -337,12 +337,14 @@ static_assert(T::type_id > 0, "T must be an *Event type"); auto write_buffer = Write(event); CHECK_EQ(write_buffer.GetBuffers().size(), 1ul); - auto& first_buffer = write_buffer.GetBuffers()[0]; - CHECK_LE(first_buffer->size(), 32ul); - std::vector<uint8_t> event_bytes(32); - memcpy(event_bytes.data(), first_buffer->data(), first_buffer->size()); + base::span<uint8_t> first_buffer = write_buffer.GetBuffers()[0]; + char event_bytes[32] = {}; + base::span(event_bytes) + .first(first_buffer.size_bytes()) + .copy_from(base::as_chars(first_buffer)); SendEventRequest send_event{false, target, mask}; + base::span(send_event.event).copy_from(event_bytes); base::ranges::copy(event_bytes, send_event.event.begin()); return XProto::SendEvent(send_event); } @@ -369,15 +371,14 @@ .long_length = static_cast<uint32_t>( amount ? length : std::numeric_limits<lentype>::max())}) .Sync(); - if (!response || response->format != CHAR_BIT * sizeof(T)) { + if (!response || response->format / 8u != sizeof(T)) { return false; } - CHECK_EQ(response->format / CHAR_BIT * response->value_len, - response->value->size()); + size_t byte_len = response->value_len * response->format / 8u; value->resize(response->value_len); - if (response->value_len > 0) { - memcpy(value->data(), response->value->data(), response->value->size()); + if (byte_len > 0u) { + memcpy(value->data(), response->value->bytes(), byte_len); } if (out_type) { *out_type = response->type; @@ -402,17 +403,8 @@ Atom type, const std::vector<T>& values) { static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, ""); - std::vector<uint8_t> data(sizeof(T) * values.size()); - if (values.size() > 0) { - memcpy(data.data(), values.data(), sizeof(T) * values.size()); - } - return ChangeProperty(ChangePropertyRequest{ - .window = static_cast<Window>(window), - .property = name, - .type = type, - .format = CHAR_BIT * sizeof(T), - .data_len = static_cast<uint32_t>(values.size()), - .data = base::RefCountedBytes::TakeVector(&data)}); + return SetArrayPropertyImpl(window, name, type, 8u * sizeof(T), + base::as_byte_span(values)); } template <typename T> @@ -506,6 +498,12 @@ bool HasNextEvent(); + Future<void> SetArrayPropertyImpl(Window window, + Atom name, + Atom type, + uint8_t format, + base::span<const uint8_t> values); + // Creates a new Request and adds it to the end of the queue. // |request_name_for_tracing| must be valid until the response is // dispatched; currently the string values are only stored in .rodata, so
diff --git a/ui/gfx/x/connection_unittest.cc b/ui/gfx/x/connection_unittest.cc index a600cbc..a2ca929 100644 --- a/ui/gfx/x/connection_unittest.cc +++ b/ui/gfx/x/connection_unittest.cc
@@ -5,6 +5,7 @@ #include "ui/gfx/x/connection.h" #include "base/memory/ref_counted_memory.h" +#include "base/numerics/safe_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/x/event.h" #include "ui/gfx/x/future.h" @@ -74,8 +75,8 @@ .property = Atom::WM_NAME, .type = Atom::STRING, .format = CHAR_BIT, - .data_len = 1, - .data = base::RefCountedBytes::TakeVector(&data), + .data_len = base::checked_cast<uint32_t>(data.size()), + .data = base::MakeRefCounted<base::RefCountedBytes>(std::move(data)), }); EXPECT_FALSE(prop_future.Sync().error);
diff --git a/ui/gfx/x/event.cc b/ui/gfx/x/event.cc index afe8e8d..f350825 100644 --- a/ui/gfx/x/event.cc +++ b/ui/gfx/x/event.cc
@@ -19,10 +19,10 @@ Event::Event() = default; -Event::Event(scoped_refptr<base::RefCountedMemory> event_bytes, +Event::Event(scoped_refptr<UnsizedRefCountedMemory> event_bytes, Connection* connection) { - auto* xcb_event = reinterpret_cast<xcb_generic_event_t*>( - const_cast<uint8_t*>(event_bytes->data())); + auto* xcb_event = + reinterpret_cast<xcb_generic_event_t*>(event_bytes->bytes()); uint8_t response_type = xcb_event->response_type & ~kSendEventMask; if (xcb_event->response_type & kSendEventMask) { send_event_ = true; @@ -38,7 +38,7 @@ const size_t extended_length = ge->length * 4; memmove(&ge->full_sequence, &ge[1], extended_length); } - connection->GetEventTypeAndOp(event_bytes->data(), &type_id_, &opcode_); + connection->GetEventTypeAndOp(event_bytes->bytes(), &type_id_, &opcode_); if (type_id_) { raw_event_ = event_bytes; }
diff --git a/ui/gfx/x/event.h b/ui/gfx/x/event.h index 5b5ff4dd..8667ab5 100644 --- a/ui/gfx/x/event.h +++ b/ui/gfx/x/event.h
@@ -45,7 +45,7 @@ // |event_bytes| is modified and will not be valid after this call. // A copy is necessary if the original data is still needed. - Event(scoped_refptr<base::RefCountedMemory> event_bytes, + Event(scoped_refptr<UnsizedRefCountedMemory> event_bytes, Connection* connection); Event(const Event&) = delete; @@ -110,7 +110,7 @@ uint32_t sequence_ = 0; // The unparsed event, or nullptr if it's already parsed. - scoped_refptr<base::RefCountedMemory> raw_event_; + scoped_refptr<UnsizedRefCountedMemory> raw_event_; // The type-erased parsed event, or nullptr if it hasn't been parsed yet. std::unique_ptr<void, Deleter> event_ = {nullptr, nullptr};
diff --git a/ui/gfx/x/gen_xproto.py b/ui/gfx/x/gen_xproto.py index 87c4e92..8c17455 100644 --- a/ui/gfx/x/gen_xproto.py +++ b/ui/gfx/x/gen_xproto.py
@@ -379,7 +379,7 @@ else: self.write('auto& %s = %s.%s;' % (field_name, obj, field_name)) - if field.type.is_list: + if field.type.is_list and field.type.is_sized: len_name = field_name + '_len' if not self.field_from_scope(len_name): len_expr = list_size(field_name, field.type) @@ -573,7 +573,7 @@ self.copy_field(case_field) def declare_switch(self, field): - return [('absl::optional<%s>' % field_type, field_name) + return [('std::optional<%s>' % field_type, field_name) for case in field.type.bitcases for field_type, field_name in self.declare_case(case)] @@ -592,7 +592,10 @@ assert (t.nmemb not in (0, 1)) if t.is_ref_counted_memory: - type_name = 'scoped_refptr<base::RefCountedMemory>' + if t.is_sized: + type_name = 'scoped_refptr<base::RefCountedMemory>' + else: + type_name = 'scoped_refptr<UnsizedRefCountedMemory>' elif t.nmemb: type_name = 'std::array<%s, %d>' % (type_name, t.nmemb) elif type_name == 'char': @@ -609,6 +612,8 @@ if t.is_ref_counted_memory: if self.is_read: self.write('%s = buffer->ReadAndAdvance(%s);' % (name, size)) + elif t.is_sized: + self.write('buf.AppendSizedBuffer(%s);' % (name)) else: self.write('buf.AppendBuffer(%s, %s);' % (name, size)) return @@ -850,7 +855,7 @@ return [] if field.type.is_switch: - return ['absl::nullopt'] * len(self.declare_switch(field)) + return ['std::nullopt'] * len(self.declare_switch(field)) if field.type.is_list or not field.type.is_container: return ['{}'] @@ -1100,6 +1105,7 @@ # xcb uses void* in some places to represent arbitrary data. field.type.is_ref_counted_memory = ( not field.type.nmemb and field.field_type[0] == 'void') + field.type.is_sized = isinstance(t, self.xcbgen.xtypes.Request) # |for_list| and |for_switch| may have already been set when # processing other fields in this structure. @@ -1225,15 +1231,15 @@ self.write('#include <cstddef>') self.write('#include <cstdint>') self.write('#include <cstring>') + self.write('#include <optional>') self.write('#include <vector>') self.write() self.write('#include "base/component_export.h"') - self.write('#include "base/memory/ref_counted_memory.h"') self.write('#include "base/memory/scoped_refptr.h"') - self.write('#include "third_party/abseil-cpp/absl/types/optional.h"') self.write('#include "base/files/scoped_file.h"') self.write('#include "ui/gfx/x/ref_counted_fd.h"') self.write('#include "ui/gfx/x/error.h"') + self.write('#include "ui/gfx/x/xproto_types.h"') imports = set(self.module.direct_imports) if self.module.namespace.is_ext: imports.add(('xproto', 'xproto'))
diff --git a/ui/gfx/x/generated_protos/bigreq.h b/ui/gfx/x/generated_protos/bigreq.h index 21632b48..4199ab1d 100644 --- a/ui/gfx/x/generated_protos/bigreq.h +++ b/ui/gfx/x/generated_protos/bigreq.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/dri3.cc b/ui/gfx/x/generated_protos/dri3.cc index 43ad6a1..b882cc5e 100644 --- a/ui/gfx/x/generated_protos/dri3.cc +++ b/ui/gfx/x/generated_protos/dri3.cc
@@ -546,9 +546,7 @@ uint32_t num_window_modifiers{}; uint32_t num_screen_modifiers{}; auto& window_modifiers = (*reply).window_modifiers; - size_t window_modifiers_len = window_modifiers.size(); auto& screen_modifiers = (*reply).screen_modifiers; - size_t screen_modifiers_len = screen_modifiers.size(); // response_type uint8_t response_type; @@ -769,11 +767,8 @@ auto& depth = (*reply).depth; auto& bpp = (*reply).bpp; auto& strides = (*reply).strides; - size_t strides_len = strides.size(); auto& offsets = (*reply).offsets; - size_t offsets_len = offsets.size(); auto& buffers = (*reply).buffers; - size_t buffers_len = buffers.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/dri3.h b/ui/gfx/x/generated_protos/dri3.h index c15ada6..17a1927 100644 --- a/ui/gfx/x/generated_protos/dri3.h +++ b/ui/gfx/x/generated_protos/dri3.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/glx.cc b/ui/gfx/x/generated_protos/glx.cc index c2f618e..6c324c22 100644 --- a/ui/gfx/x/generated_protos/glx.cc +++ b/ui/gfx/x/generated_protos/glx.cc
@@ -1576,7 +1576,6 @@ auto& num_visuals = (*reply).num_visuals; auto& num_properties = (*reply).num_properties; auto& property_list = (*reply).property_list; - size_t property_list_len = property_list.size(); // response_type uint8_t response_type; @@ -1756,9 +1755,7 @@ auto& sequence = (*reply).sequence; auto& retval = (*reply).retval; auto& data1 = (*reply).data1; - size_t data1_len = data1.size(); auto& data2 = (*reply).data2; - size_t data2_len = data2.size(); // response_type uint8_t response_type; @@ -1920,7 +1917,6 @@ auto& sequence = (*reply).sequence; uint32_t str_len{}; auto& string = (*reply).string; - size_t string_len = string.size(); // response_type uint8_t response_type; @@ -2056,7 +2052,6 @@ auto& num_FB_configs = (*reply).num_FB_configs; auto& num_properties = (*reply).num_properties; auto& property_list = (*reply).property_list; - size_t property_list_len = property_list.size(); // response_type uint8_t response_type; @@ -2295,7 +2290,6 @@ auto& sequence = (*reply).sequence; auto& num_attribs = (*reply).num_attribs; auto& attribs = (*reply).attribs; - size_t attribs_len = attribs.size(); // response_type uint8_t response_type; @@ -2553,7 +2547,6 @@ auto& sequence = (*reply).sequence; auto& num_attribs = (*reply).num_attribs; auto& attribs = (*reply).attribs; - size_t attribs_len = attribs.size(); // response_type uint8_t response_type; @@ -3302,7 +3295,6 @@ uint32_t n{}; auto& new_mode = (*reply).new_mode; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -3572,7 +3564,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -3654,7 +3645,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -3743,7 +3733,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -3825,7 +3814,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -3982,7 +3970,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4073,7 +4060,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4169,7 +4155,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4265,7 +4250,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4360,7 +4344,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4455,7 +4438,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4550,7 +4532,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4648,7 +4629,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4746,7 +4726,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4838,7 +4817,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -4930,7 +4908,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5022,7 +4999,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5113,7 +5089,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5194,7 +5169,6 @@ auto& sequence = (*reply).sequence; uint32_t n{}; auto& string = (*reply).string; - size_t string_len = string.size(); // response_type uint8_t response_type; @@ -5287,7 +5261,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5383,7 +5356,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5479,7 +5451,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5575,7 +5546,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5671,7 +5641,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5784,7 +5753,6 @@ auto& height = (*reply).height; auto& depth = (*reply).depth; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5885,7 +5853,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -5983,7 +5950,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6086,7 +6052,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6189,7 +6154,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6465,7 +6429,6 @@ auto& sequence = (*reply).sequence; auto& ret_val = (*reply).ret_val; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6595,7 +6558,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6765,7 +6727,6 @@ auto& sequence = (*reply).sequence; auto& width = (*reply).width; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6860,7 +6821,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -6958,7 +6918,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7066,7 +7025,6 @@ auto& width = (*reply).width; auto& height = (*reply).height; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7164,7 +7122,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7262,7 +7219,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7370,7 +7326,6 @@ auto& row_w = (*reply).row_w; auto& col_h = (*reply).col_h; auto& rows_and_cols = (*reply).rows_and_cols; - size_t rows_and_cols_len = rows_and_cols.size(); // response_type uint8_t response_type; @@ -7481,7 +7436,6 @@ auto& sequence = (*reply).sequence; auto& width = (*reply).width; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7576,7 +7530,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7674,7 +7627,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7784,7 +7736,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7873,7 +7824,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -7971,7 +7921,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -8068,7 +8017,6 @@ auto& sequence = (*reply).sequence; auto& size = (*reply).size; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -8203,7 +8151,6 @@ auto& sequence = (*reply).sequence; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -8364,7 +8311,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -8462,7 +8408,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -8560,7 +8505,6 @@ uint32_t n{}; auto& datum = (*reply).datum; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/glx.h b/ui/gfx/x/generated_protos/glx.h index 22abc481..c490293 100644 --- a/ui/gfx/x/generated_protos/glx.h +++ b/ui/gfx/x/generated_protos/glx.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/randr.cc b/ui/gfx/x/generated_protos/randr.cc index ca85af11..9cf8763 100644 --- a/ui/gfx/x/generated_protos/randr.cc +++ b/ui/gfx/x/generated_protos/randr.cc
@@ -799,9 +799,7 @@ auto& rate = (*reply).rate; auto& nInfo = (*reply).nInfo; auto& sizes = (*reply).sizes; - size_t sizes_len = sizes.size(); auto& rates = (*reply).rates; - size_t rates_len = rates.size(); // response_type uint8_t response_type; @@ -879,7 +877,6 @@ { uint16_t nRates{}; auto& rates = rates_elem.rates; - size_t rates_len = rates.size(); // nRates Read(&nRates, &buf); @@ -1085,11 +1082,8 @@ uint16_t num_modes{}; uint16_t names_len{}; auto& crtcs = (*reply).crtcs; - size_t crtcs_len = crtcs.size(); auto& outputs = (*reply).outputs; - size_t outputs_len = outputs.size(); auto& modes = (*reply).modes; - size_t modes_len = modes.size(); auto& names = (*reply).names; // response_type @@ -1278,11 +1272,8 @@ uint16_t num_clones{}; uint16_t name_len{}; auto& crtcs = (*reply).crtcs; - size_t crtcs_len = crtcs.size(); auto& modes = (*reply).modes; - size_t modes_len = modes.size(); auto& clones = (*reply).clones; - size_t clones_len = clones.size(); auto& name = (*reply).name; // response_type @@ -1418,7 +1409,6 @@ auto& sequence = (*reply).sequence; uint16_t num_atoms{}; auto& atoms = (*reply).atoms; - size_t atoms_len = atoms.size(); // response_type uint8_t response_type; @@ -1506,7 +1496,6 @@ auto& range = (*reply).range; auto& immutable = (*reply).immutable; auto& validValues = (*reply).validValues; - size_t validValues_len = validValues.size(); // response_type uint8_t response_type; @@ -1663,7 +1652,7 @@ buf.Write(&num_units); // data - buf.AppendBuffer(data, ((num_units) * (format)) / (8)); + buf.AppendSizedBuffer(data); Align(&buf, 4); @@ -1805,7 +1794,6 @@ auto& bytes_after = (*reply).bytes_after; auto& num_items = (*reply).num_items; auto& data = (*reply).data; - size_t data_len = data.size(); // response_type uint8_t response_type; @@ -2151,9 +2139,7 @@ uint16_t num_outputs{}; uint16_t num_possible_outputs{}; auto& outputs = (*reply).outputs; - size_t outputs_len = outputs.size(); auto& possible = (*reply).possible; - size_t possible_len = possible.size(); // response_type uint8_t response_type; @@ -2459,11 +2445,8 @@ auto& sequence = (*reply).sequence; uint16_t size{}; auto& red = (*reply).red; - size_t red_len = red.size(); auto& green = (*reply).green; - size_t green_len = green.size(); auto& blue = (*reply).blue; - size_t blue_len = blue.size(); // response_type uint8_t response_type; @@ -2634,11 +2617,8 @@ uint16_t num_modes{}; uint16_t names_len{}; auto& crtcs = (*reply).crtcs; - size_t crtcs_len = crtcs.size(); auto& outputs = (*reply).outputs; - size_t outputs_len = outputs.size(); auto& modes = (*reply).modes; - size_t modes_len = modes.size(); auto& names = (*reply).names; // response_type @@ -2923,13 +2903,9 @@ uint16_t current_len{}; uint16_t current_nparams{}; auto& pending_filter_name = (*reply).pending_filter_name; - size_t pending_filter_name_len = pending_filter_name.size(); auto& pending_params = (*reply).pending_params; - size_t pending_params_len = pending_params.size(); auto& current_filter_name = (*reply).current_filter_name; - size_t current_filter_name_len = current_filter_name.size(); auto& current_params = (*reply).current_params; - size_t current_params_len = current_params.size(); // response_type uint8_t response_type; @@ -3494,7 +3470,6 @@ auto& timestamp = (*reply).timestamp; uint16_t num_providers{}; auto& providers = (*reply).providers; - size_t providers_len = providers.size(); // response_type uint8_t response_type; @@ -3589,13 +3564,9 @@ uint16_t num_associated_providers{}; uint16_t name_len{}; auto& crtcs = (*reply).crtcs; - size_t crtcs_len = crtcs.size(); auto& outputs = (*reply).outputs; - size_t outputs_len = outputs.size(); auto& associated_providers = (*reply).associated_providers; - size_t associated_providers_len = associated_providers.size(); auto& associated_capability = (*reply).associated_capability; - size_t associated_capability_len = associated_capability.size(); auto& name = (*reply).name; // response_type @@ -3812,7 +3783,6 @@ auto& sequence = (*reply).sequence; uint16_t num_atoms{}; auto& atoms = (*reply).atoms; - size_t atoms_len = atoms.size(); // response_type uint8_t response_type; @@ -3900,7 +3870,6 @@ auto& range = (*reply).range; auto& immutable = (*reply).immutable; auto& valid_values = (*reply).valid_values; - size_t valid_values_len = valid_values.size(); // response_type uint8_t response_type; @@ -4056,7 +4025,7 @@ buf.Write(&num_items); // data - buf.AppendBuffer(data, (num_items) * ((format) / (8))); + buf.AppendSizedBuffer(data); Align(&buf, 4); @@ -4198,7 +4167,6 @@ auto& bytes_after = (*reply).bytes_after; auto& num_items = (*reply).num_items; auto& data = (*reply).data; - size_t data_len = data ? data->size() : 0; // response_type uint8_t response_type; @@ -4286,7 +4254,6 @@ uint32_t nMonitors{}; auto& nOutputs = (*reply).nOutputs; auto& monitors = (*reply).monitors; - size_t monitors_len = monitors.size(); // response_type uint8_t response_type; @@ -4330,7 +4297,6 @@ auto& width_in_millimeters = monitors_elem.width_in_millimeters; auto& height_in_millimeters = monitors_elem.height_in_millimeters; auto& outputs = monitors_elem.outputs; - size_t outputs_len = outputs.size(); // name Read(&name, &buf); @@ -4414,7 +4380,6 @@ auto& width_in_millimeters = monitorinfo.width_in_millimeters; auto& height_in_millimeters = monitorinfo.height_in_millimeters; auto& outputs = monitorinfo.outputs; - size_t outputs_len = outputs.size(); // name buf.Write(&name);
diff --git a/ui/gfx/x/generated_protos/randr.h b/ui/gfx/x/generated_protos/randr.h index e58dac1e..5e4cf5d 100644 --- a/ui/gfx/x/generated_protos/randr.h +++ b/ui/gfx/x/generated_protos/randr.h
@@ -33,11 +33,11 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "render.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 { @@ -1134,7 +1134,7 @@ Atom type{}; uint32_t bytes_after{}; uint32_t num_items{}; - scoped_refptr<base::RefCountedMemory> data{}; + scoped_refptr<UnsizedRefCountedMemory> data{}; }; using GetProviderPropertyResponse = Response<GetProviderPropertyReply>;
diff --git a/ui/gfx/x/generated_protos/render.cc b/ui/gfx/x/generated_protos/render.cc index 63623426..8cc6e9e5 100644 --- a/ui/gfx/x/generated_protos/render.cc +++ b/ui/gfx/x/generated_protos/render.cc
@@ -381,11 +381,8 @@ auto& num_visuals = (*reply).num_visuals; uint32_t num_subpixel{}; auto& formats = (*reply).formats; - size_t formats_len = formats.size(); auto& screens = (*reply).screens; - size_t screens_len = screens.size(); auto& subpixels = (*reply).subpixels; - size_t subpixels_len = subpixels.size(); // response_type uint8_t response_type; @@ -493,7 +490,6 @@ uint32_t num_depths{}; auto& fallback = screens_elem.fallback; auto& depths = screens_elem.depths; - size_t depths_len = depths.size(); // num_depths Read(&num_depths, &buf); @@ -509,7 +505,6 @@ auto& depth = depths_elem.depth; uint16_t num_visuals{}; auto& visuals = depths_elem.visuals; - size_t visuals_len = visuals.size(); // depth Read(&depth, &buf); @@ -604,7 +599,6 @@ auto& sequence = (*reply).sequence; uint32_t num_values{}; auto& values = (*reply).values; - size_t values_len = values.size(); // response_type uint8_t response_type; @@ -2382,9 +2376,7 @@ uint32_t num_aliases{}; uint32_t num_filters{}; auto& aliases = (*reply).aliases; - size_t aliases_len = aliases.size(); auto& filters = (*reply).filters; - size_t filters_len = filters.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/render.h b/ui/gfx/x/generated_protos/render.h index 511993f..d7c69d207 100644 --- a/ui/gfx/x/generated_protos/render.h +++ b/ui/gfx/x/generated_protos/render.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/screensaver.h b/ui/gfx/x/generated_protos/screensaver.h index 335de93..9778c5c 100644 --- a/ui/gfx/x/generated_protos/screensaver.h +++ b/ui/gfx/x/generated_protos/screensaver.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/shape.h b/ui/gfx/x/generated_protos/shape.h index deaca14..2a816501 100644 --- a/ui/gfx/x/generated_protos/shape.h +++ b/ui/gfx/x/generated_protos/shape.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/shm.h b/ui/gfx/x/generated_protos/shm.h index bed2915..7eb1cc2 100644 --- a/ui/gfx/x/generated_protos/shm.h +++ b/ui/gfx/x/generated_protos/shm.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/sync.h b/ui/gfx/x/generated_protos/sync.h index d9de1c89..c630fda 100644 --- a/ui/gfx/x/generated_protos/sync.h +++ b/ui/gfx/x/generated_protos/sync.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/xfixes.cc b/ui/gfx/x/generated_protos/xfixes.cc index 80bf8f37..71cfb37 100644 --- a/ui/gfx/x/generated_protos/xfixes.cc +++ b/ui/gfx/x/generated_protos/xfixes.cc
@@ -446,7 +446,6 @@ auto& yhot = (*reply).yhot; auto& cursor_serial = (*reply).cursor_serial; auto& cursor_image = (*reply).cursor_image; - size_t cursor_image_len = cursor_image.size(); // response_type uint8_t response_type; @@ -1175,7 +1174,6 @@ auto& sequence = (*reply).sequence; auto& extents = (*reply).extents; auto& rectangles = (*reply).rectangles; - size_t rectangles_len = rectangles.size(); // response_type uint8_t response_type; @@ -1499,7 +1497,6 @@ auto& atom = (*reply).atom; uint16_t nbytes{}; auto& name = (*reply).name; - size_t name_len = name.size(); // response_type uint8_t response_type; @@ -1584,9 +1581,7 @@ auto& cursor_atom = (*reply).cursor_atom; uint16_t nbytes{}; auto& cursor_image = (*reply).cursor_image; - size_t cursor_image_len = cursor_image.size(); auto& name = (*reply).name; - size_t name_len = name.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/xfixes.h b/ui/gfx/x/generated_protos/xfixes.h index 83dcef19..00476d8 100644 --- a/ui/gfx/x/generated_protos/xfixes.h +++ b/ui/gfx/x/generated_protos/xfixes.h
@@ -33,12 +33,12 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "render.h" #include "shape.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/generated_protos/xinput.cc b/ui/gfx/x/generated_protos/xinput.cc index b7e566bc..3f63d1e 100644 --- a/ui/gfx/x/generated_protos/xinput.cc +++ b/ui/gfx/x/generated_protos/xinput.cc
@@ -49,7 +49,6 @@ auto& num_valuators = (*event_).num_valuators; auto& first_valuator = (*event_).first_valuator; auto& valuators = (*event_).valuators; - size_t valuators_len = valuators.size(); // response_type uint8_t response_type; @@ -207,11 +206,8 @@ auto& num_valuators = (*event_).num_valuators; auto& classes_reported = (*event_).classes_reported; auto& buttons = (*event_).buttons; - size_t buttons_len = buttons.size(); auto& keys = (*event_).keys; - size_t keys_len = keys.size(); auto& valuators = (*event_).valuators; - size_t valuators_len = valuators.size(); // response_type uint8_t response_type; @@ -354,7 +350,6 @@ auto& device_id = (*event_).device_id; auto& sequence = (*event_).sequence; auto& keys = (*event_).keys; - size_t keys_len = keys.size(); // response_type uint8_t response_type; @@ -385,7 +380,6 @@ auto& device_id = (*event_).device_id; auto& sequence = (*event_).sequence; auto& buttons = (*event_).buttons; - size_t buttons_len = buttons.size(); // response_type uint8_t response_type; @@ -502,7 +496,6 @@ auto& sourceid = (*event_).sourceid; auto& reason = (*event_).reason; auto& classes = (*event_).classes; - size_t classes_len = classes.size(); // response_type uint8_t response_type; @@ -570,7 +563,6 @@ data.key.emplace(); uint16_t num_keys{}; auto& keys = (*data.key).keys; - size_t keys_len = keys.size(); // num_keys Read(&num_keys, &buf); @@ -586,9 +578,7 @@ data.button.emplace(); uint16_t num_buttons{}; auto& state = (*data.button).state; - size_t state_len = state.size(); auto& labels = (*data.button).labels; - size_t labels_len = labels.size(); // num_buttons Read(&num_buttons, &buf); @@ -759,11 +749,8 @@ auto& mods = (*event_).mods; auto& group = (*event_).group; auto& button_mask = (*event_).button_mask; - size_t button_mask_len = button_mask.size(); auto& valuator_mask = (*event_).valuator_mask; - size_t valuator_mask_len = valuator_mask.size(); auto& axisvalues = (*event_).axisvalues; - size_t axisvalues_len = axisvalues.size(); // response_type uint8_t response_type; @@ -1064,7 +1051,6 @@ auto& flags = (*event_).flags; uint16_t num_infos{}; auto& infos = (*event_).infos; - size_t infos_len = infos.size(); // response_type uint8_t response_type; @@ -1207,11 +1193,8 @@ uint16_t valuators_len{}; auto& flags = (*event_).flags; auto& valuator_mask = (*event_).valuator_mask; - size_t valuator_mask_len = valuator_mask.size(); auto& axisvalues = (*event_).axisvalues; - size_t axisvalues_len = axisvalues.size(); auto& axisvalues_raw = (*event_).axisvalues_raw; - size_t axisvalues_raw_len = axisvalues_raw.size(); // response_type uint8_t response_type; @@ -2123,9 +2106,7 @@ uint8_t devices_len{}; auto& devices = (*reply).devices; auto& infos = (*reply).infos; - size_t infos_len = infos.size(); auto& names = (*reply).names; - size_t names_len = names.size(); // response_type uint8_t response_type; @@ -2348,7 +2329,6 @@ auto& sequence = (*reply).sequence; uint8_t num_classes{}; auto& class_info = (*reply).class_info; - size_t class_info_len = class_info.size(); // response_type uint8_t response_type; @@ -2619,9 +2599,7 @@ uint16_t num_this_classes{}; uint16_t num_all_classes{}; auto& this_classes = (*reply).this_classes; - size_t this_classes_len = this_classes.size(); auto& all_classes = (*reply).all_classes; - size_t all_classes_len = all_classes.size(); // response_type uint8_t response_type; @@ -2775,7 +2753,6 @@ auto& sequence = (*reply).sequence; uint16_t num_classes{}; auto& classes = (*reply).classes; - size_t classes_len = classes.size(); // response_type uint8_t response_type; @@ -2872,7 +2849,6 @@ auto& num_axes = (*reply).num_axes; auto& device_mode = (*reply).device_mode; auto& events = (*reply).events; - size_t events_len = events.size(); // response_type uint8_t response_type; @@ -2909,7 +2885,6 @@ { auto& time = events_elem.time; auto& axisvalues = events_elem.axisvalues; - size_t axisvalues_len = axisvalues.size(); // time Read(&time, &buf); @@ -3798,7 +3773,6 @@ auto& sequence = (*reply).sequence; uint16_t num_feedbacks{}; auto& feedbacks = (*reply).feedbacks; - size_t feedbacks_len = feedbacks.size(); // response_type uint8_t response_type; @@ -3853,7 +3827,6 @@ auto& click = (*data.keyboard).click; auto& percent = (*data.keyboard).percent; auto& auto_repeats = (*data.keyboard).auto_repeats; - size_t auto_repeats_len = auto_repeats.size(); // pitch Read(&pitch, &buf); @@ -3908,7 +3881,6 @@ auto& max_symbols = (*data.string).max_symbols; uint16_t num_keysyms{}; auto& keysyms = (*data.string).keysyms; - size_t keysyms_len = keysyms.size(); // max_symbols Read(&max_symbols, &buf); @@ -4097,7 +4069,6 @@ if (CaseEq(data_expr, FeedbackClass::String)) { uint16_t num_keysyms{}; auto& keysyms = (*data.string).keysyms; - size_t keysyms_len = keysyms.size(); // pad1 Pad(&buf, 2); @@ -4222,7 +4193,6 @@ auto& sequence = (*reply).sequence; auto& keysyms_per_keycode = (*reply).keysyms_per_keycode; auto& keysyms = (*reply).keysyms; - size_t keysyms_len = keysyms.size(); // response_type uint8_t response_type; @@ -4368,7 +4338,6 @@ auto& sequence = (*reply).sequence; auto& keycodes_per_modifier = (*reply).keycodes_per_modifier; auto& keymaps = (*reply).keymaps; - size_t keymaps_len = keymaps.size(); // response_type uint8_t response_type; @@ -4546,7 +4515,6 @@ auto& sequence = (*reply).sequence; uint8_t map_size{}; auto& map = (*reply).map; - size_t map_len = map.size(); // response_type uint8_t response_type; @@ -4726,7 +4694,6 @@ auto& sequence = (*reply).sequence; uint8_t num_classes{}; auto& classes = (*reply).classes; - size_t classes_len = classes.size(); // response_type uint8_t response_type; @@ -4771,7 +4738,6 @@ data.key.emplace(); auto& num_keys = (*data.key).num_keys; auto& keys = (*data.key).keys; - size_t keys_len = keys.size(); // num_keys Read(&num_keys, &buf); @@ -4789,7 +4755,6 @@ data.button.emplace(); auto& num_buttons = (*data.button).num_buttons; auto& buttons = (*data.button).buttons; - size_t buttons_len = buttons.size(); // num_buttons Read(&num_buttons, &buf); @@ -4808,7 +4773,6 @@ uint8_t num_valuators{}; auto& mode = (*data.valuator).mode; auto& valuators = (*data.valuator).valuators; - size_t valuators_len = valuators.size(); // num_valuators Read(&num_valuators, &buf); @@ -5078,11 +5042,8 @@ data.resolution.emplace(); uint32_t num_valuators{}; auto& resolution_values = (*data.resolution).resolution_values; - size_t resolution_values_len = resolution_values.size(); auto& resolution_min = (*data.resolution).resolution_min; - size_t resolution_min_len = resolution_min.size(); auto& resolution_max = (*data.resolution).resolution_max; - size_t resolution_max_len = resolution_max.size(); // num_valuators Read(&num_valuators, &buf); @@ -5265,7 +5226,6 @@ auto& first_valuator = (*data.resolution).first_valuator; uint8_t num_valuators{}; auto& resolution_values = (*data.resolution).resolution_values; - size_t resolution_values_len = resolution_values.size(); // first_valuator buf.Write(&first_valuator); @@ -5465,7 +5425,6 @@ auto& sequence = (*reply).sequence; uint16_t num_atoms{}; auto& atoms = (*reply).atoms; - size_t atoms_len = atoms.size(); // response_type uint8_t response_type; @@ -5559,7 +5518,6 @@ auto items_expr = format; if (CaseEq(items_expr, PropertyFormat::c_8Bits)) { auto& data8 = *items.data8; - size_t data8_len = data8.size(); // data8 CHECK_EQ(static_cast<size_t>(num_items), data8.size()); @@ -5573,7 +5531,6 @@ } if (CaseEq(items_expr, PropertyFormat::c_16Bits)) { auto& data16 = *items.data16; - size_t data16_len = data16.size(); // data16 CHECK_EQ(static_cast<size_t>(num_items), data16.size()); @@ -5587,7 +5544,6 @@ } if (CaseEq(items_expr, PropertyFormat::c_32Bits)) { auto& data32 = *items.data32; - size_t data32_len = data32.size(); // data32 CHECK_EQ(static_cast<size_t>(num_items), data32.size()); @@ -5778,7 +5734,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_8Bits)) { items.data8.emplace(); auto& data8 = *items.data8; - size_t data8_len = data8.size(); // data8 data8.resize(num_items); @@ -5793,7 +5748,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_16Bits)) { items.data16.emplace(); auto& data16 = *items.data16; - size_t data16_len = data16.size(); // data16 data16.resize(num_items); @@ -5808,7 +5762,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_32Bits)) { items.data32.emplace(); auto& data32 = *items.data32; - size_t data32_len = data32.size(); // data32 data32.resize(num_items); @@ -6565,7 +6518,6 @@ auto& sequence = (*reply).sequence; uint16_t num_infos{}; auto& infos = (*reply).infos; - size_t infos_len = infos.size(); // response_type uint8_t response_type; @@ -6600,7 +6552,6 @@ auto& enabled = infos_elem.enabled; auto& name = infos_elem.name; auto& classes = infos_elem.classes; - size_t classes_len = classes.size(); // deviceid Read(&deviceid, &buf); @@ -6662,7 +6613,6 @@ data.key.emplace(); uint16_t num_keys{}; auto& keys = (*data.key).keys; - size_t keys_len = keys.size(); // num_keys Read(&num_keys, &buf); @@ -6678,9 +6628,7 @@ data.button.emplace(); uint16_t num_buttons{}; auto& state = (*data.button).state; - size_t state_len = state.size(); auto& labels = (*data.button).labels; - size_t labels_len = labels.size(); // num_buttons Read(&num_buttons, &buf); @@ -7302,7 +7250,6 @@ auto& sequence = (*reply).sequence; uint16_t num_modifiers{}; auto& modifiers = (*reply).modifiers; - size_t modifiers_len = modifiers.size(); // response_type uint8_t response_type; @@ -7470,7 +7417,6 @@ auto& sequence = (*reply).sequence; uint16_t num_properties{}; auto& properties = (*reply).properties; - size_t properties_len = properties.size(); // response_type uint8_t response_type; @@ -7561,7 +7507,6 @@ auto items_expr = format; if (CaseEq(items_expr, PropertyFormat::c_8Bits)) { auto& data8 = *items.data8; - size_t data8_len = data8.size(); // data8 CHECK_EQ(static_cast<size_t>(num_items), data8.size()); @@ -7575,7 +7520,6 @@ } if (CaseEq(items_expr, PropertyFormat::c_16Bits)) { auto& data16 = *items.data16; - size_t data16_len = data16.size(); // data16 CHECK_EQ(static_cast<size_t>(num_items), data16.size()); @@ -7589,7 +7533,6 @@ } if (CaseEq(items_expr, PropertyFormat::c_32Bits)) { auto& data32 = *items.data32; - size_t data32_len = data32.size(); // data32 CHECK_EQ(static_cast<size_t>(num_items), data32.size()); @@ -7772,7 +7715,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_8Bits)) { items.data8.emplace(); auto& data8 = *items.data8; - size_t data8_len = data8.size(); // data8 data8.resize(num_items); @@ -7787,7 +7729,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_16Bits)) { items.data16.emplace(); auto& data16 = *items.data16; - size_t data16_len = data16.size(); // data16 data16.resize(num_items); @@ -7802,7 +7743,6 @@ if (CaseEq(items_expr, Input::PropertyFormat::c_32Bits)) { items.data32.emplace(); auto& data32 = *items.data32; - size_t data32_len = data32.size(); // data32 data32.resize(num_items); @@ -7863,7 +7803,6 @@ auto& sequence = (*reply).sequence; uint16_t num_masks{}; auto& masks = (*reply).masks; - size_t masks_len = masks.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/xinput.h b/ui/gfx/x/generated_protos/xinput.h index 0a32b76e..eb8c7822 100644 --- a/ui/gfx/x/generated_protos/xinput.h +++ b/ui/gfx/x/generated_protos/xinput.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xfixes.h" #include "xproto.h"
diff --git a/ui/gfx/x/generated_protos/xkb.cc b/ui/gfx/x/generated_protos/xkb.cc index 04c2d9c..0fd5c93 100644 --- a/ui/gfx/x/generated_protos/xkb.cc +++ b/ui/gfx/x/generated_protos/xkb.cc
@@ -787,7 +787,6 @@ auto& mods = (*event_).mods; auto& group = (*event_).group; auto& message = (*event_).message; - size_t message_len = message.size(); // response_type uint8_t response_type; @@ -1700,7 +1699,6 @@ auto& accessXTimeoutValues = (*reply).accessXTimeoutValues; auto& enabledControls = (*reply).enabledControls; auto& perKeyRepeat = (*reply).perKeyRepeat; - size_t perKeyRepeat_len = perKeyRepeat.size(); // response_type uint8_t response_type; @@ -2348,7 +2346,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeyTypes)) { map.types_rtrn.emplace(); auto& types_rtrn = *map.types_rtrn; - size_t types_rtrn_len = types_rtrn.size(); // types_rtrn types_rtrn.resize(nTypes); @@ -2362,9 +2359,7 @@ uint8_t nMapEntries{}; auto& hasPreserve = types_rtrn_elem.hasPreserve; auto& map = types_rtrn_elem.map; - size_t map_len = map.size(); auto& preserve = types_rtrn_elem.preserve; - size_t preserve_len = preserve.size(); // mods_mask uint8_t tmp99; @@ -2461,7 +2456,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeySyms)) { map.syms_rtrn.emplace(); auto& syms_rtrn = *map.syms_rtrn; - size_t syms_rtrn_len = syms_rtrn.size(); // syms_rtrn syms_rtrn.resize(nKeySyms); @@ -2469,12 +2463,10 @@ // syms_rtrn_elem { auto& kt_index = syms_rtrn_elem.kt_index; - size_t kt_index_len = kt_index.size(); auto& groupInfo = syms_rtrn_elem.groupInfo; auto& width = syms_rtrn_elem.width; uint16_t nSyms{}; auto& syms = syms_rtrn_elem.syms; - size_t syms_len = syms.size(); // kt_index for (auto& kt_index_elem : kt_index) { @@ -2504,9 +2496,7 @@ map.acts_rtrn_count.emplace(); map.acts_rtrn_acts.emplace(); auto& acts_rtrn_count = *map.acts_rtrn_count; - size_t acts_rtrn_count_len = acts_rtrn_count.size(); auto& acts_rtrn_acts = *map.acts_rtrn_acts; - size_t acts_rtrn_acts_len = acts_rtrn_acts.size(); // acts_rtrn_count acts_rtrn_count.resize(nKeyActions); @@ -2528,7 +2518,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeyBehaviors)) { map.behaviors_rtrn.emplace(); auto& behaviors_rtrn = *map.behaviors_rtrn; - size_t behaviors_rtrn_len = behaviors_rtrn.size(); // behaviors_rtrn behaviors_rtrn.resize(totalKeyBehaviors); @@ -2552,7 +2541,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::VirtualMods)) { map.vmods_rtrn.emplace(); auto& vmods_rtrn = *map.vmods_rtrn; - size_t vmods_rtrn_len = vmods_rtrn.size(); // vmods_rtrn vmods_rtrn.resize(PopCount(virtualMods)); @@ -2569,7 +2557,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::ExplicitComponents)) { map.explicit_rtrn.emplace(); auto& explicit_rtrn = *map.explicit_rtrn; - size_t explicit_rtrn_len = explicit_rtrn.size(); // explicit_rtrn explicit_rtrn.resize(totalKeyExplicit); @@ -2595,7 +2582,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::ModifierMap)) { map.modmap_rtrn.emplace(); auto& modmap_rtrn = *map.modmap_rtrn; - size_t modmap_rtrn_len = modmap_rtrn.size(); // modmap_rtrn modmap_rtrn.resize(totalModMapKeys); @@ -2621,7 +2607,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::VirtualModMap)) { map.vmodmap_rtrn.emplace(); auto& vmodmap_rtrn = *map.vmodmap_rtrn; - size_t vmodmap_rtrn_len = vmodmap_rtrn.size(); // vmodmap_rtrn vmodmap_rtrn.resize(totalVModMapKeys); @@ -2796,7 +2781,6 @@ auto values_expr = present; if (CaseAnd(values_expr, MapPart::KeyTypes)) { auto& types = *values.types; - size_t types_len = types.size(); // types CHECK_EQ(static_cast<size_t>(nTypes), types.size()); @@ -2810,9 +2794,7 @@ uint8_t nMapEntries{}; auto& preserve = types_elem.preserve; auto& entries = types_elem.entries; - size_t entries_len = entries.size(); auto& preserve_entries = types_elem.preserve_entries; - size_t preserve_entries_len = preserve_entries.size(); // mask uint8_t tmp115; @@ -2895,7 +2877,6 @@ } if (CaseAnd(values_expr, MapPart::KeySyms)) { auto& syms = *values.syms; - size_t syms_len = syms.size(); // syms CHECK_EQ(static_cast<size_t>(nKeySyms), syms.size()); @@ -2903,12 +2884,10 @@ // syms_elem { auto& kt_index = syms_elem.kt_index; - size_t kt_index_len = kt_index.size(); auto& groupInfo = syms_elem.groupInfo; auto& width = syms_elem.width; uint16_t nSyms{}; auto& syms = syms_elem.syms; - size_t syms_len = syms.size(); // kt_index for (auto& kt_index_elem : kt_index) { @@ -2937,9 +2916,7 @@ } if (CaseAnd(values_expr, MapPart::KeyActions)) { auto& actionsCount = *values.actionsCount; - size_t actionsCount_len = actionsCount.size(); auto& actions = *values.actions; - size_t actions_len = actions.size(); // actionsCount CHECK_EQ(static_cast<size_t>(nKeyActions), actionsCount.size()); @@ -2960,7 +2937,6 @@ } if (CaseAnd(values_expr, MapPart::KeyBehaviors)) { auto& behaviors = *values.behaviors; - size_t behaviors_len = behaviors.size(); // behaviors CHECK_EQ(static_cast<size_t>(totalKeyBehaviors), behaviors.size()); @@ -2983,7 +2959,6 @@ } if (CaseAnd(values_expr, MapPart::VirtualMods)) { auto& vmods = *values.vmods; - size_t vmods_len = vmods.size(); // vmods CHECK_EQ(static_cast<size_t>(PopCount(virtualMods)), vmods.size()); @@ -2997,7 +2972,6 @@ } if (CaseAnd(values_expr, MapPart::ExplicitComponents)) { auto& c_explicit = *values.c_explicit; - size_t c_explicit_len = c_explicit.size(); // c_explicit CHECK_EQ(static_cast<size_t>(totalKeyExplicit), c_explicit.size()); @@ -3019,7 +2993,6 @@ } if (CaseAnd(values_expr, MapPart::ModifierMap)) { auto& modmap = *values.modmap; - size_t modmap_len = modmap.size(); // modmap CHECK_EQ(static_cast<size_t>(totalModMapKeys), modmap.size()); @@ -3041,7 +3014,6 @@ } if (CaseAnd(values_expr, MapPart::VirtualModMap)) { auto& vmodmap = *values.vmodmap; - size_t vmodmap_len = vmodmap.size(); // vmodmap CHECK_EQ(static_cast<size_t>(totalVModMapKeys), vmodmap.size()); @@ -3212,9 +3184,7 @@ uint16_t nSIRtrn{}; auto& nTotalSI = (*reply).nTotalSI; auto& si_rtrn = (*reply).si_rtrn; - size_t si_rtrn_len = si_rtrn.size(); auto& group_rtrn = (*reply).group_rtrn; - size_t group_rtrn_len = group_rtrn.size(); // response_type uint8_t response_type; @@ -3285,7 +3255,6 @@ { auto& type = action.type; auto& data = action.data; - size_t data_len = data.size(); // type uint8_t tmp129; @@ -3424,7 +3393,6 @@ { auto& type = action.type; auto& data = action.data; - size_t data_len = data.size(); // type uint8_t tmp136; @@ -3614,7 +3582,6 @@ auto& realIndicators = (*reply).realIndicators; auto& nIndicators = (*reply).nIndicators; auto& maps = (*reply).maps; - size_t maps_len = maps.size(); // response_type uint8_t response_type; @@ -4265,7 +4232,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyTypeNames)) { valueList.typeNames.emplace(); auto& typeNames = *valueList.typeNames; - size_t typeNames_len = typeNames.size(); // typeNames typeNames.resize(nTypes); @@ -4278,9 +4244,7 @@ valueList.nLevelsPerType.emplace(); valueList.ktLevelNames.emplace(); auto& nLevelsPerType = *valueList.nLevelsPerType; - size_t nLevelsPerType_len = nLevelsPerType.size(); auto& ktLevelNames = *valueList.ktLevelNames; - size_t ktLevelNames_len = ktLevelNames.size(); // nLevelsPerType nLevelsPerType.resize(nTypes); @@ -4304,7 +4268,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::IndicatorNames)) { valueList.indicatorNames.emplace(); auto& indicatorNames = *valueList.indicatorNames; - size_t indicatorNames_len = indicatorNames.size(); // indicatorNames indicatorNames.resize(PopCount(indicators)); @@ -4316,7 +4279,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::VirtualModNames)) { valueList.virtualModNames.emplace(); auto& virtualModNames = *valueList.virtualModNames; - size_t virtualModNames_len = virtualModNames.size(); // virtualModNames virtualModNames.resize(PopCount(virtualMods)); @@ -4328,7 +4290,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::GroupNames)) { valueList.groups.emplace(); auto& groups = *valueList.groups; - size_t groups_len = groups.size(); // groups groups.resize(PopCount(groupNames)); @@ -4340,7 +4301,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyNames)) { valueList.keyNames.emplace(); auto& keyNames = *valueList.keyNames; - size_t keyNames_len = keyNames.size(); // keyNames keyNames.resize(nKeys); @@ -4348,7 +4308,6 @@ // keyNames_elem { auto& name = keyNames_elem.name; - size_t name_len = name.size(); // name for (auto& name_elem : name) { @@ -4361,7 +4320,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyAliases)) { valueList.keyAliases.emplace(); auto& keyAliases = *valueList.keyAliases; - size_t keyAliases_len = keyAliases.size(); // keyAliases keyAliases.resize(nKeyAliases); @@ -4369,9 +4327,7 @@ // keyAliases_elem { auto& real = keyAliases_elem.real; - size_t real_len = real.size(); auto& alias = keyAliases_elem.alias; - size_t alias_len = alias.size(); // real for (auto& real_elem : real) { @@ -4390,7 +4346,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::RGNames)) { valueList.radioGroupNames.emplace(); auto& radioGroupNames = *valueList.radioGroupNames; - size_t radioGroupNames_len = radioGroupNames.size(); // radioGroupNames radioGroupNames.resize(nRadioGroups); @@ -4554,7 +4509,6 @@ } if (CaseAnd(values_expr, NameDetail::KeyTypeNames)) { auto& typeNames = *values.typeNames; - size_t typeNames_len = typeNames.size(); // typeNames CHECK_EQ(static_cast<size_t>(nTypes), typeNames.size()); @@ -4565,9 +4519,7 @@ } if (CaseAnd(values_expr, NameDetail::KTLevelNames)) { auto& nLevelsPerType = *values.nLevelsPerType; - size_t nLevelsPerType_len = nLevelsPerType.size(); auto& ktLevelNames = *values.ktLevelNames; - size_t ktLevelNames_len = ktLevelNames.size(); // nLevelsPerType CHECK_EQ(static_cast<size_t>(nTypes), nLevelsPerType.size()); @@ -4590,7 +4542,6 @@ } if (CaseAnd(values_expr, NameDetail::IndicatorNames)) { auto& indicatorNames = *values.indicatorNames; - size_t indicatorNames_len = indicatorNames.size(); // indicatorNames CHECK_EQ(static_cast<size_t>(PopCount(indicators)), indicatorNames.size()); @@ -4601,7 +4552,6 @@ } if (CaseAnd(values_expr, NameDetail::VirtualModNames)) { auto& virtualModNames = *values.virtualModNames; - size_t virtualModNames_len = virtualModNames.size(); // virtualModNames CHECK_EQ(static_cast<size_t>(PopCount(virtualMods)), @@ -4613,7 +4563,6 @@ } if (CaseAnd(values_expr, NameDetail::GroupNames)) { auto& groups = *values.groups; - size_t groups_len = groups.size(); // groups CHECK_EQ(static_cast<size_t>(PopCount(groupNames)), groups.size()); @@ -4624,7 +4573,6 @@ } if (CaseAnd(values_expr, NameDetail::KeyNames)) { auto& keyNames = *values.keyNames; - size_t keyNames_len = keyNames.size(); // keyNames CHECK_EQ(static_cast<size_t>(nKeys), keyNames.size()); @@ -4632,7 +4580,6 @@ // keyNames_elem { auto& name = keyNames_elem.name; - size_t name_len = name.size(); // name for (auto& name_elem : name) { @@ -4644,7 +4591,6 @@ } if (CaseAnd(values_expr, NameDetail::KeyAliases)) { auto& keyAliases = *values.keyAliases; - size_t keyAliases_len = keyAliases.size(); // keyAliases CHECK_EQ(static_cast<size_t>(nKeyAliases), keyAliases.size()); @@ -4652,9 +4598,7 @@ // keyAliases_elem { auto& real = keyAliases_elem.real; - size_t real_len = real.size(); auto& alias = keyAliases_elem.alias; - size_t alias_len = alias.size(); // real for (auto& real_elem : real) { @@ -4672,7 +4616,6 @@ } if (CaseAnd(values_expr, NameDetail::RGNames)) { auto& radioGroupNames = *values.radioGroupNames; - size_t radioGroupNames_len = radioGroupNames.size(); // radioGroupNames CHECK_EQ(static_cast<size_t>(nRadioGroups), radioGroupNames.size()); @@ -4934,17 +4877,11 @@ uint16_t nGeometries{}; auto& extra = (*reply).extra; auto& keymaps = (*reply).keymaps; - size_t keymaps_len = keymaps.size(); auto& keycodes = (*reply).keycodes; - size_t keycodes_len = keycodes.size(); auto& types = (*reply).types; - size_t types_len = types.size(); auto& compatMaps = (*reply).compatMaps; - size_t compatMaps_len = compatMaps.size(); auto& symbols = (*reply).symbols; - size_t symbols_len = symbols.size(); auto& geometries = (*reply).geometries; - size_t geometries_len = geometries.size(); // response_type uint8_t response_type; @@ -4992,7 +4929,6 @@ auto& flags = keymaps_elem.flags; uint16_t length{}; auto& string = keymaps_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5020,7 +4956,6 @@ auto& flags = keycodes_elem.flags; uint16_t length{}; auto& string = keycodes_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5048,7 +4983,6 @@ auto& flags = types_elem.flags; uint16_t length{}; auto& string = types_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5076,7 +5010,6 @@ auto& flags = compatMaps_elem.flags; uint16_t length{}; auto& string = compatMaps_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5104,7 +5037,6 @@ auto& flags = symbols_elem.flags; uint16_t length{}; auto& string = symbols_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5132,7 +5064,6 @@ auto& flags = geometries_elem.flags; uint16_t length{}; auto& string = geometries_elem.string; - size_t string_len = string.size(); // flags Read(&flags, &buf); @@ -5410,7 +5341,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeyTypes)) { map.types_rtrn.emplace(); auto& types_rtrn = *map.types_rtrn; - size_t types_rtrn_len = types_rtrn.size(); // types_rtrn types_rtrn.resize(nTypes); @@ -5424,9 +5354,7 @@ uint8_t nMapEntries{}; auto& hasPreserve = types_rtrn_elem.hasPreserve; auto& map = types_rtrn_elem.map; - size_t map_len = map.size(); auto& preserve = types_rtrn_elem.preserve; - size_t preserve_len = preserve.size(); // mods_mask uint8_t tmp197; @@ -5523,7 +5451,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeySyms)) { map.syms_rtrn.emplace(); auto& syms_rtrn = *map.syms_rtrn; - size_t syms_rtrn_len = syms_rtrn.size(); // syms_rtrn syms_rtrn.resize(nKeySyms); @@ -5531,12 +5458,10 @@ // syms_rtrn_elem { auto& kt_index = syms_rtrn_elem.kt_index; - size_t kt_index_len = kt_index.size(); auto& groupInfo = syms_rtrn_elem.groupInfo; auto& width = syms_rtrn_elem.width; uint16_t nSyms{}; auto& syms = syms_rtrn_elem.syms; - size_t syms_len = syms.size(); // kt_index for (auto& kt_index_elem : kt_index) { @@ -5566,9 +5491,7 @@ map.acts_rtrn_count.emplace(); map.acts_rtrn_acts.emplace(); auto& acts_rtrn_count = *map.acts_rtrn_count; - size_t acts_rtrn_count_len = acts_rtrn_count.size(); auto& acts_rtrn_acts = *map.acts_rtrn_acts; - size_t acts_rtrn_acts_len = acts_rtrn_acts.size(); // acts_rtrn_count acts_rtrn_count.resize(nKeyActions); @@ -5590,7 +5513,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::KeyBehaviors)) { map.behaviors_rtrn.emplace(); auto& behaviors_rtrn = *map.behaviors_rtrn; - size_t behaviors_rtrn_len = behaviors_rtrn.size(); // behaviors_rtrn behaviors_rtrn.resize(totalKeyBehaviors); @@ -5614,7 +5536,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::VirtualMods)) { map.vmods_rtrn.emplace(); auto& vmods_rtrn = *map.vmods_rtrn; - size_t vmods_rtrn_len = vmods_rtrn.size(); // vmods_rtrn vmods_rtrn.resize(PopCount(virtualMods)); @@ -5631,7 +5552,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::ExplicitComponents)) { map.explicit_rtrn.emplace(); auto& explicit_rtrn = *map.explicit_rtrn; - size_t explicit_rtrn_len = explicit_rtrn.size(); // explicit_rtrn explicit_rtrn.resize(totalKeyExplicit); @@ -5657,7 +5577,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::ModifierMap)) { map.modmap_rtrn.emplace(); auto& modmap_rtrn = *map.modmap_rtrn; - size_t modmap_rtrn_len = modmap_rtrn.size(); // modmap_rtrn modmap_rtrn.resize(totalModMapKeys); @@ -5683,7 +5602,6 @@ if (CaseAnd(map_expr, Xkb::MapPart::VirtualModMap)) { map.vmodmap_rtrn.emplace(); auto& vmodmap_rtrn = *map.vmodmap_rtrn; - size_t vmodmap_rtrn_len = vmodmap_rtrn.size(); // vmodmap_rtrn vmodmap_rtrn.resize(totalVModMapKeys); @@ -5718,9 +5636,7 @@ uint16_t nSIRtrn{}; auto& nTotalSI = (*replies.compat_map).nTotalSI; auto& si_rtrn = (*replies.compat_map).si_rtrn; - size_t si_rtrn_len = si_rtrn.size(); auto& group_rtrn = (*replies.compat_map).group_rtrn; - size_t group_rtrn_len = group_rtrn.size(); // compatmap_type Read(&compatmap_type, &buf); @@ -5789,7 +5705,6 @@ { auto& type = action.type; auto& data = action.data; - size_t data_len = data.size(); // type uint8_t tmp213; @@ -5842,7 +5757,6 @@ auto& realIndicators = (*replies.indicator_maps).realIndicators; uint8_t nIndicators{}; auto& maps = (*replies.indicator_maps).maps; - size_t maps_len = maps.size(); // indicatormap_type Read(&indicatormap_type, &buf); @@ -6049,7 +5963,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyTypeNames)) { valueList.typeNames.emplace(); auto& typeNames = *valueList.typeNames; - size_t typeNames_len = typeNames.size(); // typeNames typeNames.resize(nTypes); @@ -6062,9 +5975,7 @@ valueList.nLevelsPerType.emplace(); valueList.ktLevelNames.emplace(); auto& nLevelsPerType = *valueList.nLevelsPerType; - size_t nLevelsPerType_len = nLevelsPerType.size(); auto& ktLevelNames = *valueList.ktLevelNames; - size_t ktLevelNames_len = ktLevelNames.size(); // nLevelsPerType nLevelsPerType.resize(nTypes); @@ -6088,7 +5999,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::IndicatorNames)) { valueList.indicatorNames.emplace(); auto& indicatorNames = *valueList.indicatorNames; - size_t indicatorNames_len = indicatorNames.size(); // indicatorNames indicatorNames.resize(PopCount(indicators)); @@ -6100,7 +6010,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::VirtualModNames)) { valueList.virtualModNames.emplace(); auto& virtualModNames = *valueList.virtualModNames; - size_t virtualModNames_len = virtualModNames.size(); // virtualModNames virtualModNames.resize(PopCount(virtualMods)); @@ -6112,7 +6021,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::GroupNames)) { valueList.groups.emplace(); auto& groups = *valueList.groups; - size_t groups_len = groups.size(); // groups groups.resize(PopCount(groupNames)); @@ -6124,7 +6032,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyNames)) { valueList.keyNames.emplace(); auto& keyNames = *valueList.keyNames; - size_t keyNames_len = keyNames.size(); // keyNames keyNames.resize(nKeys); @@ -6132,7 +6039,6 @@ // keyNames_elem { auto& name = keyNames_elem.name; - size_t name_len = name.size(); // name for (auto& name_elem : name) { @@ -6145,7 +6051,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::KeyAliases)) { valueList.keyAliases.emplace(); auto& keyAliases = *valueList.keyAliases; - size_t keyAliases_len = keyAliases.size(); // keyAliases keyAliases.resize(nKeyAliases); @@ -6153,9 +6058,7 @@ // keyAliases_elem { auto& real = keyAliases_elem.real; - size_t real_len = real.size(); auto& alias = keyAliases_elem.alias; - size_t alias_len = alias.size(); // real for (auto& real_elem : real) { @@ -6174,7 +6077,6 @@ if (CaseAnd(valueList_expr, Xkb::NameDetail::RGNames)) { valueList.radioGroupNames.emplace(); auto& radioGroupNames = *valueList.radioGroupNames; - size_t radioGroupNames_len = radioGroupNames.size(); // radioGroupNames radioGroupNames.resize(nRadioGroups); @@ -6259,9 +6161,7 @@ { uint16_t length{}; auto& string = labelFont.string; - size_t string_len = string.size(); auto& alignment_pad = labelFont.alignment_pad; - size_t alignment_pad_len = alignment_pad ? alignment_pad->size() : 0; // length Read(&length, &buf); @@ -6381,11 +6281,8 @@ auto& devType = (*reply).devType; uint16_t nameLen{}; auto& name = (*reply).name; - size_t name_len = name.size(); auto& btnActions = (*reply).btnActions; - size_t btnActions_len = btnActions.size(); auto& leds = (*reply).leds; - size_t leds_len = leds.size(); // response_type uint8_t response_type; @@ -6481,9 +6378,7 @@ auto& physIndicators = leds_elem.physIndicators; auto& state = leds_elem.state; auto& names = leds_elem.names; - size_t names_len = names.size(); auto& maps = leds_elem.maps; - size_t maps_len = maps.size(); // ledClass uint16_t tmp234; @@ -6642,9 +6537,7 @@ auto& physIndicators = leds_elem.physIndicators; auto& state = leds_elem.state; auto& names = leds_elem.names; - size_t names_len = names.size(); auto& maps = leds_elem.maps; - size_t maps_len = maps.size(); // ledClass uint16_t tmp244;
diff --git a/ui/gfx/x/generated_protos/xkb.h b/ui/gfx/x/generated_protos/xkb.h index b1bb8a5..c18d756 100644 --- a/ui/gfx/x/generated_protos/xkb.h +++ b/ui/gfx/x/generated_protos/xkb.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 { @@ -557,7 +557,7 @@ } std::string string{}; - scoped_refptr<base::RefCountedMemory> alignment_pad{}; + scoped_refptr<UnsizedRefCountedMemory> alignment_pad{}; }; struct KTMapEntry {
diff --git a/ui/gfx/x/generated_protos/xproto.cc b/ui/gfx/x/generated_protos/xproto.cc index 08f573da..c3866c8 100644 --- a/ui/gfx/x/generated_protos/xproto.cc +++ b/ui/gfx/x/generated_protos/xproto.cc
@@ -820,7 +820,6 @@ auto& buf = *buffer; auto& keys = (*event_).keys; - size_t keys_len = keys.size(); // response_type uint8_t response_type; @@ -4126,7 +4125,7 @@ buf.Write(&data_len); // data - buf.AppendBuffer(data, ((data_len) * (format)) / (8)); + buf.AppendSizedBuffer(data); Align(&buf, 4); @@ -5695,7 +5694,6 @@ auto& sequence = (*reply).sequence; auto& keys = (*reply).keys; - size_t keys_len = keys.size(); // response_type uint8_t response_type; @@ -8244,7 +8242,7 @@ Pad(&buf, 2); // data - buf.AppendBuffer(data, data_len); + buf.AppendSizedBuffer(data); Align(&buf, 4); @@ -8338,7 +8336,6 @@ auto& sequence = (*reply).sequence; auto& visual = (*reply).visual; auto& data = (*reply).data; - size_t data_len = data ? data->size() : 0; // response_type uint8_t response_type; @@ -10279,7 +10276,6 @@ auto& keysyms_per_keycode = (*reply).keysyms_per_keycode; auto& sequence = (*reply).sequence; auto& keysyms = (*reply).keysyms; - size_t keysyms_len = keysyms.size(); // response_type uint8_t response_type; @@ -10468,7 +10464,6 @@ auto& bell_pitch = (*reply).bell_pitch; auto& bell_duration = (*reply).bell_duration; auto& auto_repeats = (*reply).auto_repeats; - size_t auto_repeats_len = auto_repeats.size(); // response_type uint8_t response_type; @@ -11379,7 +11374,6 @@ auto& keycodes_per_modifier = (*reply).keycodes_per_modifier; auto& sequence = (*reply).sequence; auto& keycodes = (*reply).keycodes; - size_t keycodes_len = keycodes.size(); // response_type uint8_t response_type;
diff --git a/ui/gfx/x/generated_protos/xproto.h b/ui/gfx/x/generated_protos/xproto.h index 7722813..f820adbd3 100644 --- a/ui/gfx/x/generated_protos/xproto.h +++ b/ui/gfx/x/generated_protos/xproto.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" namespace x11 { @@ -1696,7 +1696,7 @@ Atom type{}; uint32_t bytes_after{}; uint32_t value_len{}; - scoped_refptr<base::RefCountedMemory> value{}; + scoped_refptr<UnsizedRefCountedMemory> value{}; }; using GetPropertyResponse = Response<GetPropertyReply>; @@ -2298,7 +2298,7 @@ uint8_t depth{}; uint16_t sequence{}; VisualId visual{}; - scoped_refptr<base::RefCountedMemory> data{}; + scoped_refptr<UnsizedRefCountedMemory> data{}; }; using GetImageResponse = Response<GetImageReply>;
diff --git a/ui/gfx/x/generated_protos/xtest.h b/ui/gfx/x/generated_protos/xtest.h index da67d78c..178e9655 100644 --- a/ui/gfx/x/generated_protos/xtest.h +++ b/ui/gfx/x/generated_protos/xtest.h
@@ -33,10 +33,10 @@ #include "base/component_export.h" #include "base/files/scoped_file.h" -#include "base/memory/ref_counted_memory.h" #include "base/memory/scoped_refptr.h" #include "ui/gfx/x/error.h" #include "ui/gfx/x/ref_counted_fd.h" +#include "ui/gfx/x/xproto_types.h" #include "xproto.h" namespace x11 {
diff --git a/ui/gfx/x/property_cache.h b/ui/gfx/x/property_cache.h index d9ec464..bcaa468 100644 --- a/ui/gfx/x/property_cache.h +++ b/ui/gfx/x/property_cache.h
@@ -53,7 +53,7 @@ if (size) { *size = response->value_len; } - return response->value->front_as<T>(); + return response->value->cast_to<T>(); } template <typename T>
diff --git a/ui/gfx/x/property_cache_unittest.cc b/ui/gfx/x/property_cache_unittest.cc index bdd53893..fefe1bc 100644 --- a/ui/gfx/x/property_cache_unittest.cc +++ b/ui/gfx/x/property_cache_unittest.cc
@@ -135,7 +135,7 @@ EXPECT_EQ(response->bytes_after, 0u); EXPECT_EQ(response->format, 32); EXPECT_EQ(response->type, Atom::CARDINAL); - EXPECT_EQ(*response->value->front_as<uint32_t>(), 1234u); + EXPECT_EQ(*response->value->cast_to<uint32_t>(), 1234u); EXPECT_EQ(response->value_len, 1u); // GetAs() should do the same thing as Get().
diff --git a/ui/gfx/x/window_cache.cc b/ui/gfx/x/window_cache.cc index b374f6f..74f5d22 100644 --- a/ui/gfx/x/window_cache.cc +++ b/ui/gfx/x/window_cache.cc
@@ -384,7 +384,7 @@ } else if (atom == gtk_frame_extents_) { if (response->format == CHAR_BIT * sizeof(int32_t) && response->value_len == 4) { - const int32_t* frame_extents = response->value->front_as<int32_t>(); + const int32_t* frame_extents = response->value->cast_to<int32_t>(); info->gtk_frame_extents_px = gfx::Insets::TLBR(frame_extents[2], frame_extents[0], frame_extents[3], frame_extents[1]);
diff --git a/ui/gfx/x/xproto_internal.cc b/ui/gfx/x/xproto_internal.cc index b4668cba..c9eac9a62 100644 --- a/ui/gfx/x/xproto_internal.cc +++ b/ui/gfx/x/xproto_internal.cc
@@ -11,49 +11,45 @@ namespace x11 { MallocedRefCountedMemory::MallocedRefCountedMemory(void* data) - : data_(reinterpret_cast<uint8_t*>(data)) {} - -const uint8_t* MallocedRefCountedMemory::front() const { - return data_.get(); -} - -size_t MallocedRefCountedMemory::size() const { - // There's no easy way to tell how large malloc'ed data is. - NOTREACHED(); - return 0; -} + : data_(static_cast<uint8_t*>(data)) {} MallocedRefCountedMemory::~MallocedRefCountedMemory() = default; +void* MallocedRefCountedMemory::data() { + return data_.get(); +} + +const void* MallocedRefCountedMemory::data() const { + return data_.get(); +} + OffsetRefCountedMemory::OffsetRefCountedMemory( - scoped_refptr<base::RefCountedMemory> memory, + scoped_refptr<UnsizedRefCountedMemory> memory, size_t offset, size_t size) - : memory_(memory), offset_(offset), size_(size) {} - -const uint8_t* OffsetRefCountedMemory::front() const { - return memory_->front() + offset_; -} - -size_t OffsetRefCountedMemory::size() const { - return size_; -} + : memory_(memory), offset_(offset) {} OffsetRefCountedMemory::~OffsetRefCountedMemory() = default; -UnretainedRefCountedMemory::UnretainedRefCountedMemory(const void* data) - : data_(reinterpret_cast<const uint8_t*>(data)) {} +void* OffsetRefCountedMemory::data() { + return memory_->bytes() + offset_; +} -const uint8_t* UnretainedRefCountedMemory::front() const { +const void* OffsetRefCountedMemory::data() const { + return memory_->bytes() + offset_; +} + +UnretainedRefCountedMemory::UnretainedRefCountedMemory(void* data) + : data_(data) {} + +UnretainedRefCountedMemory::~UnretainedRefCountedMemory() = default; + +void* UnretainedRefCountedMemory::data() { return data_; } -size_t UnretainedRefCountedMemory::size() const { - // There's no easy way to tell how large malloc'ed data is. - NOTREACHED(); - return 0; +const void* UnretainedRefCountedMemory::data() const { + return data_; } -UnretainedRefCountedMemory::~UnretainedRefCountedMemory() = default; - } // namespace x11
diff --git a/ui/gfx/x/xproto_internal.h b/ui/gfx/x/xproto_internal.h index 8ee3813..56a7d695 100644 --- a/ui/gfx/x/xproto_internal.h +++ b/ui/gfx/x/xproto_internal.h
@@ -43,19 +43,15 @@ // Calls free() on the underlying data when the count drops to 0. class COMPONENT_EXPORT(X11) MallocedRefCountedMemory - : public base::RefCountedMemory { + : public UnsizedRefCountedMemory { public: explicit MallocedRefCountedMemory(void* data); MallocedRefCountedMemory(const MallocedRefCountedMemory&) = delete; MallocedRefCountedMemory& operator=(const MallocedRefCountedMemory&) = delete; - const uint8_t* front() const override; - - size_t size() const override; - private: - struct deleter { + struct Deleter { void operator()(uint8_t* data) { if (data) { free(data); @@ -64,61 +60,64 @@ }; ~MallocedRefCountedMemory() override; - std::unique_ptr<uint8_t, deleter> data_; + // UnsizedRefCountedMemory: + void* data() LIFETIME_BOUND override; + const void* data() const LIFETIME_BOUND override; + + std::unique_ptr<uint8_t[], Deleter> data_; }; // Wraps another RefCountedMemory, giving a view into it. Similar to // base::StringPiece, the data is some contiguous subarray, but unlike // StringPiece, a counted reference is kept on the underlying memory. class COMPONENT_EXPORT(X11) OffsetRefCountedMemory - : public base::RefCountedMemory { + : public UnsizedRefCountedMemory { public: - OffsetRefCountedMemory(scoped_refptr<base::RefCountedMemory> memory, + OffsetRefCountedMemory(scoped_refptr<UnsizedRefCountedMemory> memory, size_t offset, size_t size); OffsetRefCountedMemory(const OffsetRefCountedMemory&) = delete; OffsetRefCountedMemory& operator=(const OffsetRefCountedMemory&) = delete; - const uint8_t* front() const override; - - size_t size() const override; - private: ~OffsetRefCountedMemory() override; - scoped_refptr<base::RefCountedMemory> memory_; + // UnsizedRefCountedMemory: + void* data() LIFETIME_BOUND override; + const void* data() const LIFETIME_BOUND override; + + scoped_refptr<UnsizedRefCountedMemory> memory_; size_t offset_; - size_t size_; }; // Wraps a bare pointer and does not take any action when the reference count // reaches 0. This is used to wrap stack-alloctaed or persistent data so we can // pass those to Read/ReadEvent/ReadReply which expect RefCountedMemory. class COMPONENT_EXPORT(X11) UnretainedRefCountedMemory - : public base::RefCountedMemory { + : public UnsizedRefCountedMemory { public: - explicit UnretainedRefCountedMemory(const void* data); + explicit UnretainedRefCountedMemory(void* data); UnretainedRefCountedMemory(const UnretainedRefCountedMemory&) = delete; UnretainedRefCountedMemory& operator=(const UnretainedRefCountedMemory&) = delete; - const uint8_t* front() const override; - - size_t size() const override; - private: ~UnretainedRefCountedMemory() override; - const uint8_t* const data_; + // UnsizedRefCountedMemory: + void* data() LIFETIME_BOUND override; + const void* data() const LIFETIME_BOUND override; + + raw_ptr<void> data_; }; template <typename T> void Read(T* t, ReadBuffer* buf) { static_assert(std::is_trivially_copyable<T>::value, ""); detail::VerifyAlignment(t, buf->offset); - memcpy(t, buf->data->data() + buf->offset, sizeof(*t)); + memcpy(t, buf->data->bytes() + buf->offset, sizeof(*t)); buf->offset += sizeof(*t); }
diff --git a/ui/gfx/x/xproto_types.cc b/ui/gfx/x/xproto_types.cc index 5cdc104f..3f4a1b3 100644 --- a/ui/gfx/x/xproto_types.cc +++ b/ui/gfx/x/xproto_types.cc
@@ -25,7 +25,34 @@ } // namespace -ReadBuffer::ReadBuffer(scoped_refptr<base::RefCountedMemory> data, +ThrowAwaySizeRefCountedMemory::ThrowAwaySizeRefCountedMemory( + std::vector<uint8_t> data) + : data_(std::move(data)) {} + +ThrowAwaySizeRefCountedMemory::~ThrowAwaySizeRefCountedMemory() = default; + +void* ThrowAwaySizeRefCountedMemory::data() { + return data_.data(); +} + +const void* ThrowAwaySizeRefCountedMemory::data() const { + return data_.data(); +} + +SizedRefCountedMemory::SizedRefCountedMemory( + scoped_refptr<UnsizedRefCountedMemory> mem, + size_t size) + : mem_(std::move(mem)), size_(size) {} + +SizedRefCountedMemory::~SizedRefCountedMemory() = default; + +base::span<const uint8_t> SizedRefCountedMemory::AsSpan() const { + // SAFETY: This relies on the constructor being called with a valid buffer + // and size pair. + return UNSAFE_BUFFERS(base::span(mem_->bytes(), size_)); +} + +ReadBuffer::ReadBuffer(scoped_refptr<UnsizedRefCountedMemory> data, bool setup_message) : data(data) { // X connection setup uses a special reply without the standard header, see: @@ -34,7 +61,7 @@ if (setup_message) return; - const auto* reply_header = reinterpret_cast<const ReplyHeader*>(data->data()); + const ReplyHeader* reply_header = data->cast_to<const ReplyHeader>(); // Only replies can have FDs, not events or errors. if (reply_header->response_type == kResponseTypeReply) { @@ -43,7 +70,7 @@ size_t reply_length = 32 + 4 * reply_header->length; // libxcb stores the fds after the reply data. - fds = reinterpret_cast<const int*>(data->data() + reply_length); + fds = reinterpret_cast<const int*>(data->bytes() + reply_length); } } @@ -51,7 +78,7 @@ ReadBuffer::~ReadBuffer() = default; -scoped_refptr<base::RefCountedMemory> ReadBuffer::ReadAndAdvance( +scoped_refptr<UnsizedRefCountedMemory> ReadBuffer::ReadAndAdvance( size_t length) { auto buf = base::MakeRefCounted<OffsetRefCountedMemory>(data, offset, length); offset += length; @@ -68,21 +95,41 @@ WriteBuffer::~WriteBuffer() = default; -void WriteBuffer::AppendBuffer(scoped_refptr<base::RefCountedMemory> buffer, +void WriteBuffer::AppendBuffer(scoped_refptr<UnsizedRefCountedMemory> buffer, size_t size) { AppendCurrentBuffer(); - buffers_.push_back(buffer); + sized_buffers_.push_back( + // SAFETY: This relies on the caller to pass a correct size. + UNSAFE_BUFFERS(base::span(buffer->bytes(), size))); + owned_buffers_.push_back(buffer); offset_ += size; } -std::vector<scoped_refptr<base::RefCountedMemory>>& WriteBuffer::GetBuffers() { +void WriteBuffer::AppendSizedBuffer( + scoped_refptr<base::RefCountedMemory> buffer) { + AppendCurrentBuffer(); + std::vector<uint8_t> v(buffer->size()); + base::span(v).copy_from(*buffer); + sized_buffers_.push_back(v); + owned_buffers_.push_back(ThrowAwaySizeRefCountedMemory::From(std::move(v))); + offset_ += buffer->size(); +} + +base::span<base::span<uint8_t>> WriteBuffer::GetBuffers() { if (!current_buffer_.empty()) AppendCurrentBuffer(); - return buffers_; + return sized_buffers_; +} + +void WriteBuffer::OffsetFirstBuffer(size_t offset) { + sized_buffers_[0u] = sized_buffers_[0u].subspan(offset); } void WriteBuffer::AppendCurrentBuffer() { - buffers_.push_back(base::RefCountedBytes::TakeVector(¤t_buffer_)); + sized_buffers_.push_back(base::span(current_buffer_)); + owned_buffers_.push_back( + ThrowAwaySizeRefCountedMemory::From(std::move(current_buffer_))); + current_buffer_.clear(); } } // namespace x11
diff --git a/ui/gfx/x/xproto_types.h b/ui/gfx/x/xproto_types.h index 0a6256b0..53597865 100644 --- a/ui/gfx/x/xproto_types.h +++ b/ui/gfx/x/xproto_types.h
@@ -20,8 +20,92 @@ class Error; -using RawReply = scoped_refptr<base::RefCountedMemory>; -using RawError = scoped_refptr<base::RefCountedMemory>; +// A memory buffer where the size of the memory buffer is unknown because its +// given as `void*` from a C api which expects us to dynamically cast it to +// another type later. Use of this type is not sound as a mistake will cause +// Undefined Behaviour. +class COMPONENT_EXPORT(X11) UnsizedRefCountedMemory + : public base::RefCountedThreadSafe<UnsizedRefCountedMemory> { + public: + uint8_t* bytes() { return cast_to<uint8_t>(); } + const uint8_t* bytes() const { return cast_to<const uint8_t>(); } + + // Converts the inner pointer to a `T*`. If the type is incorrect, this + // results in Undefined Behaviour. + template <class T> + T* cast_to() { + return reinterpret_cast<T*>(data()); + } + template <class T> + requires(std::is_const_v<T>) + T* cast_to() const { + return reinterpret_cast<T*>(data()); + } + + protected: + friend class base::RefCountedThreadSafe<UnsizedRefCountedMemory>; + virtual ~UnsizedRefCountedMemory() = default; + + virtual void* data() LIFETIME_BOUND = 0; + virtual const void* data() const LIFETIME_BOUND = 0; +}; + +// Convert from a sized memory buffer to an unsized one, in order to use the +// buffer in void* APIs that pass the size separately. +class COMPONENT_EXPORT(X11) ThrowAwaySizeRefCountedMemory final + : public UnsizedRefCountedMemory { + public: + static scoped_refptr<ThrowAwaySizeRefCountedMemory> From( + std::vector<uint8_t> data) { + return new ThrowAwaySizeRefCountedMemory(std::move(data)); + } + + ThrowAwaySizeRefCountedMemory(const ThrowAwaySizeRefCountedMemory&) = delete; + ThrowAwaySizeRefCountedMemory& operator=( + const ThrowAwaySizeRefCountedMemory&) = delete; + + private: + explicit ThrowAwaySizeRefCountedMemory(std::vector<uint8_t> data); + + // UnsizedRefCountedMemory: + void* data() LIFETIME_BOUND override; + const void* data() const LIFETIME_BOUND override; + + ~ThrowAwaySizeRefCountedMemory() override; + + std::vector<uint8_t> data_; +}; + +// Convert from an unsized memory buffer to a sized one, by specifying the size. +class COMPONENT_EXPORT(X11) SizedRefCountedMemory final + : public base::RefCountedMemory { + public: + // Safety: The caller must ensure that the `mem` buffer points to at least + // `size` many bytes or Undefined Behaviour can result. + UNSAFE_BUFFER_USAGE static scoped_refptr<SizedRefCountedMemory> From( + scoped_refptr<UnsizedRefCountedMemory> mem, + size_t size) { + return new SizedRefCountedMemory(std::move(mem), size); + } + + SizedRefCountedMemory(const SizedRefCountedMemory&) = delete; + SizedRefCountedMemory& operator=(const SizedRefCountedMemory&) = delete; + + private: + SizedRefCountedMemory(scoped_refptr<UnsizedRefCountedMemory> mem, + size_t size); + + // RefCountedMemory: + base::span<const uint8_t> AsSpan() const LIFETIME_BOUND override; + + ~SizedRefCountedMemory() override; + + scoped_refptr<UnsizedRefCountedMemory> mem_; + size_t size_; +}; + +using RawReply = scoped_refptr<UnsizedRefCountedMemory>; +using RawError = scoped_refptr<UnsizedRefCountedMemory>; using ResponseCallback = base::OnceCallback<void(RawReply reply, std::unique_ptr<Error> error)>; @@ -46,7 +130,7 @@ // Wraps data read from the connection. struct COMPONENT_EXPORT(X11) ReadBuffer { - explicit ReadBuffer(scoped_refptr<base::RefCountedMemory> data, + explicit ReadBuffer(scoped_refptr<UnsizedRefCountedMemory> data, bool setup_message = false); ReadBuffer(const ReadBuffer&) = delete; @@ -54,11 +138,11 @@ ~ReadBuffer(); - scoped_refptr<base::RefCountedMemory> ReadAndAdvance(size_t length); + scoped_refptr<UnsizedRefCountedMemory> ReadAndAdvance(size_t length); int TakeFd(); - scoped_refptr<base::RefCountedMemory> data; + scoped_refptr<UnsizedRefCountedMemory> data; size_t offset = 0; raw_ptr<const int, AllowPtrArithmetic> fds = nullptr; }; @@ -73,9 +157,17 @@ ~WriteBuffer(); - void AppendBuffer(scoped_refptr<base::RefCountedMemory> buffer, size_t size); + // Safety: The `buffer` must point to at least `size` many bytes. + UNSAFE_BUFFER_USAGE void AppendBuffer( + scoped_refptr<UnsizedRefCountedMemory> buffer, + size_t size); - std::vector<scoped_refptr<base::RefCountedMemory>>& GetBuffers(); + void AppendSizedBuffer(scoped_refptr<base::RefCountedMemory> buffer); + + base::span<base::span<uint8_t>> GetBuffers(); + + // Advance the pointer in the first buffer by `offset`. + void OffsetFirstBuffer(size_t offset); size_t offset() const { return offset_; } @@ -93,7 +185,8 @@ private: void AppendCurrentBuffer(); - std::vector<scoped_refptr<base::RefCountedMemory>> buffers_; + std::vector<scoped_refptr<UnsizedRefCountedMemory>> owned_buffers_; + std::vector<base::span<uint8_t>> sized_buffers_; std::vector<uint8_t> current_buffer_; size_t offset_ = 0; std::vector<int> fds_;
diff --git a/ui/gl/dc_layer_overlay_params.cc b/ui/gl/dc_layer_overlay_params.cc index 74ca138..e78f487 100644 --- a/ui/gl/dc_layer_overlay_params.cc +++ b/ui/gl/dc_layer_overlay_params.cc
@@ -9,4 +9,7 @@ DCLayerOverlayParams::DCLayerOverlayParams() = default; DCLayerOverlayParams::~DCLayerOverlayParams() = default; +DCLayerOverlayParams::VideoParams::VideoParams() = default; +DCLayerOverlayParams::VideoParams::~VideoParams() = default; + } // namespace gl
diff --git a/ui/gl/dc_layer_overlay_params.h b/ui/gl/dc_layer_overlay_params.h index 3a7dce93..55932ed 100644 --- a/ui/gl/dc_layer_overlay_params.h +++ b/ui/gl/dc_layer_overlay_params.h
@@ -63,22 +63,26 @@ // blended behind |overlay_image|. std::optional<SkColor4f> background_color; - // - // Below are parameters only used for |SwapChainPresenter|. - // + // Parameters for video overlays, only used by |SwapChainPresenter|. + struct VideoParams { + VideoParams(); + ~VideoParams(); - gfx::ProtectedVideoType protected_video_type = - gfx::ProtectedVideoType::kClear; + gfx::ProtectedVideoType protected_video_type = + gfx::ProtectedVideoType::kClear; - gfx::ColorSpace color_space; + gfx::ColorSpace color_space; - gfx::HDRMetadata hdr_metadata; + gfx::HDRMetadata hdr_metadata; - // Indication of the overlay to be detected as possible full screen - // letterboxing. - // Go to viz::OverlayCandidate::possible_video_fullscreen_letterboxing for the - // details. - bool possible_video_fullscreen_letterboxing = false; + // Indication of the overlay to be detected as possible full screen + // letterboxing. + // Go to viz::OverlayCandidate::possible_video_fullscreen_letterboxing for + // the details. + bool possible_video_fullscreen_letterboxing = false; + }; + + VideoParams video_params; }; } // namespace gl
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc index 94705f0..eedc25e9 100644 --- a/ui/gl/dcomp_presenter_unittest.cc +++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -303,7 +303,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -328,7 +328,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -351,7 +351,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -387,7 +387,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -414,7 +414,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -447,7 +447,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -469,7 +469,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); } @@ -502,8 +502,8 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); - params->protected_video_type = gfx::ProtectedVideoType::kClear; + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.protected_video_type = gfx::ProtectedVideoType::kClear; presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -524,8 +524,9 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); - params->protected_video_type = gfx::ProtectedVideoType::kSoftwareProtected; + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.protected_video_type = + gfx::ProtectedVideoType::kSoftwareProtected; presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -719,7 +720,7 @@ DCLayerOverlayImage(texture_size, texture), /*content_rect_override=*/gfx::RectF(content_rect)); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -877,7 +878,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(texture_size); - params->color_space = color_space; + params->video_params.color_space = color_space; presenter_->ScheduleDCLayer(std::move(params)); } @@ -889,7 +890,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(window_size); - params->color_space = color_space; + params->video_params.color_space = color_space; presenter_->ScheduleDCLayer(std::move(params)); } @@ -945,7 +946,7 @@ auto params = CreateParamsFromImage( DCLayerOverlayImage(y_size, nv12_pixmap.data(), stride)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1011,7 +1012,7 @@ CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture), /*content_rect_override=*/gfx::RectF()); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1158,7 +1159,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1180,7 +1181,7 @@ CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture), /*content_rect_override=*/gfx::RectF(30, 30)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1204,7 +1205,7 @@ CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = on_screen_rect; params->clip_rect = on_screen_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1234,7 +1235,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = on_screen_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1330,7 +1331,6 @@ auto dc_layer_params = CreateParamsFromImage(DCLayerOverlayImage(swap_chain_size, swap_chain)); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); dc_layer_params->z_order = 1; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); @@ -1353,7 +1353,6 @@ auto dc_layer_params = CreateParamsFromImage(DCLayerOverlayImage(swap_chain_size, swap_chain)); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1373,7 +1372,6 @@ auto dc_layer_params = CreateParamsFromImage(DCLayerOverlayImage(swap_chain_size, swap_chain)); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -1393,7 +1391,6 @@ auto dc_layer_params = CreateParamsFromImage(DCLayerOverlayImage(swap_chain_size, swap_chain)); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2222,7 +2219,7 @@ auto params = CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); presenter_->ScheduleDCLayer(std::move(params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2343,9 +2340,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2393,9 +2390,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); } @@ -2451,9 +2448,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); } @@ -2531,9 +2528,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2620,9 +2617,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2654,9 +2651,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2693,9 +2690,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2744,9 +2741,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -2794,9 +2791,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); } @@ -2852,9 +2849,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); } @@ -2932,9 +2929,9 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; - dc_layer_params->possible_video_fullscreen_letterboxing = true; + dc_layer_params->video_params.possible_video_fullscreen_letterboxing = true; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); PresentAndCheckSwapResult(gfx::SwapResult::SWAP_ACK); @@ -3045,7 +3042,7 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; presenter_->ScheduleDCLayer(std::move(dc_layer_params)); @@ -3151,7 +3148,7 @@ dc_layer_params->quad_rect = quad_rect; dc_layer_params->transform = quad_to_root_transform; dc_layer_params->clip_rect = clip_rect; - dc_layer_params->color_space = gfx::ColorSpace::CreateREC709(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateREC709(); dc_layer_params->z_order = 1; presenter_->ScheduleDCLayer(std::move(dc_layer_params));
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc index c6e41a0..58d068b 100644 --- a/ui/gl/direct_composition_surface_win_unittest.cc +++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -325,7 +325,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -351,7 +351,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -375,7 +375,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -414,7 +414,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -444,7 +444,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -481,7 +481,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -505,7 +505,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); } @@ -542,8 +542,8 @@ params->overlay_image.emplace(texture_size, texture); params->quad_rect = gfx::Rect(window_size); params->content_rect = gfx::RectF(texture_size); - params->color_space = gfx::ColorSpace::CreateREC709(); - params->protected_video_type = gfx::ProtectedVideoType::kClear; + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.protected_video_type = gfx::ProtectedVideoType::kClear; surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -566,8 +566,9 @@ params->overlay_image.emplace(texture_size, texture); params->quad_rect = gfx::Rect(window_size); params->content_rect = gfx::RectF(texture_size); - params->color_space = gfx::ColorSpace::CreateREC709(); - params->protected_video_type = gfx::ProtectedVideoType::kSoftwareProtected; + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.protected_video_type = + gfx::ProtectedVideoType::kSoftwareProtected; surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -629,7 +630,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(content_rect); params->quad_rect = quad_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -704,7 +705,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(texture_size); - params->color_space = color_space; + params->video_params.color_space = color_space; surface_->ScheduleDCLayer(std::move(params)); } @@ -718,7 +719,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(window_size); - params->color_space = color_space; + params->video_params.color_space = color_space; surface_->ScheduleDCLayer(std::move(params)); } @@ -783,7 +784,7 @@ DCLayerOverlayImage(y_size, nv12_pixmap.data(), stride); params->content_rect = gfx::RectF(y_size); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -861,7 +862,7 @@ auto params = std::make_unique<DCLayerOverlayParams>(); params->overlay_image.emplace(texture_size, texture); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1021,7 +1022,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1044,7 +1045,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(30, 30); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1070,7 +1071,7 @@ params->content_rect = gfx::RectF(50, 50); params->quad_rect = on_screen_rect; params->clip_rect = on_screen_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1102,7 +1103,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(50, 50); params->quad_rect = on_screen_rect; - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface_->ScheduleDCLayer(std::move(params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1205,7 +1206,7 @@ DCLayerOverlayImage(swap_chain_size, swap_chain); dc_layer_params->content_rect = gfx::RectF(swap_chain_size); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateSRGB(); surface_->ScheduleDCLayer(std::move(dc_layer_params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1231,7 +1232,7 @@ DCLayerOverlayImage(swap_chain_size, swap_chain); dc_layer_params->content_rect = gfx::RectF(swap_chain_size); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateSRGB(); surface_->ScheduleDCLayer(std::move(dc_layer_params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1255,7 +1256,7 @@ DCLayerOverlayImage(swap_chain_size, swap_chain); dc_layer_params->content_rect = gfx::RectF(swap_chain_size); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateSRGB(); surface_->ScheduleDCLayer(std::move(dc_layer_params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1279,7 +1280,7 @@ DCLayerOverlayImage(swap_chain_size, swap_chain); dc_layer_params->content_rect = gfx::RectF(swap_chain_size); dc_layer_params->quad_rect = gfx::Rect(window_size); - dc_layer_params->color_space = gfx::ColorSpace::CreateSRGB(); + dc_layer_params->video_params.color_space = gfx::ColorSpace::CreateSRGB(); surface_->ScheduleDCLayer(std::move(dc_layer_params)); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, @@ -1436,7 +1437,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(window_size); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); surface->ScheduleDCLayer(std::move(params)); } @@ -1496,7 +1497,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); // Overlay params->z_order = 1; surface_->ScheduleDCLayer(std::move(params)); @@ -1520,7 +1521,7 @@ params->overlay_image.emplace(texture_size, texture); params->content_rect = gfx::RectF(texture_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateREC709(); + params->video_params.color_space = gfx::ColorSpace::CreateREC709(); // Underlay params->z_order = -1; surface_->ScheduleDCLayer(std::move(params)); @@ -1547,7 +1548,7 @@ params->overlay_image = DCLayerOverlayImage(swap_chain_size, swap_chain); params->content_rect = gfx::RectF(swap_chain_size); params->quad_rect = gfx::Rect(100, 100); - params->color_space = gfx::ColorSpace::CreateSRGB(); + params->video_params.color_space = gfx::ColorSpace::CreateSRGB(); params->z_order = z_order; surface->ScheduleDCLayer(std::move(params)); }
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc index 4500a13..830d65e 100644 --- a/ui/gl/swap_chain_presenter.cc +++ b/ui/gl/swap_chain_presenter.cc
@@ -768,7 +768,8 @@ visual_transform, visual_clip_rect); // Adjustment for the full screen letterboxing scenario. - if (!size_adjusted && params.possible_video_fullscreen_letterboxing) { + if (!size_adjusted && + params.video_params.possible_video_fullscreen_letterboxing) { AdjustTargetForFullScreenLetterboxing( monitor_size, params, overlay_onscreen_rect, swap_chain_size, visual_transform, visual_clip_rect, dest_size, target_rect); @@ -793,7 +794,8 @@ visual_transform, visual_clip_rect); // Adjustment for the full screen letterboxing scenario. - if (!size_adjusted && params.possible_video_fullscreen_letterboxing) { + if (!size_adjusted && + params.video_params.possible_video_fullscreen_letterboxing) { AdjustTargetForFullScreenLetterboxingF( monitor_size_float, params, overlay_onscreen_rect, swap_chain_size, visual_transform, visual_clip_rect, dest_size, target_rect); @@ -1983,7 +1985,7 @@ bool swap_chain_resized = swap_chain_size_ != swap_chain_size; - gfx::ColorSpace input_color_space = params.color_space; + gfx::ColorSpace input_color_space = params.video_params.color_space; if (!input_color_space.IsValid()) { input_color_space = gfx::ColorSpace::CreateREC709(); } @@ -2000,14 +2002,15 @@ enable_vp_auto_hdr_ && !is_on_battery_power_; bool use_hdr_swap_chain = - ((content_is_hdr && params.hdr_metadata.IsValid()) || use_vp_auto_hdr); + ((content_is_hdr && params.video_params.hdr_metadata.IsValid()) || + use_vp_auto_hdr); - DXGI_FORMAT swap_chain_format = - GetSwapChainFormat(params.protected_video_type, use_hdr_swap_chain); + DXGI_FORMAT swap_chain_format = GetSwapChainFormat( + params.video_params.protected_video_type, use_hdr_swap_chain); bool swap_chain_format_changed = swap_chain_format != swap_chain_format_; - bool toggle_protected_video = - swap_chain_protected_video_type_ != params.protected_video_type; + bool toggle_protected_video = swap_chain_protected_video_type_ != + params.video_params.protected_video_type; bool contents_changed = last_overlay_image_ != params.overlay_image; @@ -2049,7 +2052,7 @@ if (!swap_chain_ || swap_chain_resized || swap_chain_format_changed || toggle_protected_video) { if (!ReallocateSwapChain(swap_chain_size, swap_chain_format, - params.protected_video_type)) { + params.video_params.protected_video_type)) { ReleaseSwapChainResources(); return false; } @@ -2069,9 +2072,9 @@ } std::optional<DXGI_HDR_METADATA_HDR10> stream_metadata; - if (params.hdr_metadata.IsValid()) { - stream_metadata = - gl::HDRMetadataHelperWin::HDRMetadataToDXGI(params.hdr_metadata); + if (params.video_params.hdr_metadata.IsValid()) { + stream_metadata = gl::HDRMetadataHelperWin::HDRMetadataToDXGI( + params.video_params.hdr_metadata); } if (!VideoProcessorBlt(std::move(input_texture), input_level, @@ -2299,7 +2302,8 @@ dcomp_surface_proxy->SetRect(mapped_rect); } - dcomp_surface_proxy->SetProtectedVideoType(params.protected_video_type); + dcomp_surface_proxy->SetProtectedVideoType( + params.video_params.protected_video_type); // If |dcomp_surface_proxy| size is {1, 1}, the texture was initialized // without knowledge of output size; reset |content_| so it's not added to the
diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h index 8524cc6a7..9822c77 100644 --- a/ui/message_center/public/cpp/notification.h +++ b/ui/message_center/public/cpp/notification.h
@@ -223,10 +223,6 @@ // Flag if the notification is pinned. If true, the notification is pinned // and the user can't remove it. bool pinned = false; - - // Presents a shortcut that will dismiss the notification when performed. - // Only used in in ash pinned notifications. See `PinnedNotificationView`. - std::u16string shortcut_text; #endif // BUILDFLAG(IS_CHROMEOS) // Vibration pattern to play when displaying the notification. There must be @@ -525,14 +521,6 @@ void set_pinned(bool pinned) { optional_fields_.pinned = pinned; } #endif // BUILDFLAG(IS_CHROMEOS) - const std::u16string shortcut_text() const { -#if BUILDFLAG(IS_CHROMEOS) - return optional_fields_.shortcut_text; -#else - return std::u16string(); -#endif // BUILDFLAG(IS_CHROMEOS) - } - // Gets a text for spoken feedback. const std::u16string& accessible_name() const { return optional_fields_.accessible_name;
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/ui/ozone/platform/wayland/host/wayland_clipboard.cc index 5f56dab4..f25c794 100644 --- a/ui/ozone/platform/wayland/host/wayland_clipboard.cc +++ b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -189,8 +189,9 @@ auto it = offered_data_.find(mime_type); if (it == offered_data_.end() && mime_type == ui::kMimeTypeTextUtf8) it = offered_data_.find(ui::kMimeTypeText); - if (it != offered_data_.end()) - contents->assign(it->second->data().begin(), it->second->data().end()); + if (it != offered_data_.end()) { + *contents = base::as_string_view(*it->second); + } } // The device manager used to access data device and create data sources.
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc b/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc index 38664a8..fd5153c 100644 --- a/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_clipboard_unittest.cc
@@ -366,7 +366,7 @@ base::MockCallback<PlatformClipboard::RequestDataClosure> callback; EXPECT_CALL(callback, Run(_)).WillOnce([&text](PlatformClipboard::Data data) { ASSERT_TRUE(data); - text = std::string(data->front_as<const char>(), data->size()); + text = std::string(base::as_string_view(*data)); }); clipboard_->RequestClipboardData(WhichBufferToUse(), kMimeTypeTextUtf8, @@ -391,7 +391,7 @@ base::MockCallback<PlatformClipboard::RequestDataClosure> callback; EXPECT_CALL(callback, Run(_)).WillOnce([&text](PlatformClipboard::Data data) { ASSERT_TRUE(data); - text = std::string(data->front_as<const char>(), data->size()); + text = std::string(base::as_string_view(*data)); }); clipboard_->RequestClipboardData(WhichBufferToUse(), kMimeTypeTextUtf8, @@ -466,7 +466,7 @@ base::MockCallback<PlatformClipboard::RequestDataClosure> got_text; EXPECT_CALL(got_text, Run(_)).WillOnce([&](PlatformClipboard::Data data) { ASSERT_NE(nullptr, data); - text = std::string(data->front_as<const char>(), data->size()); + text = std::string(base::as_string_view(*data)); }); clipboard_->RequestClipboardData(WhichBufferToUse(), kMimeTypeTextUtf8, got_text.Get()); @@ -543,7 +543,7 @@ std::string html; base::MockCallback<PlatformClipboard::RequestDataClosure> got_html; EXPECT_CALL(got_html, Run(_)).WillOnce([&](PlatformClipboard::Data data) { - html = std::string(data->front_as<const char>(), data->size()); + html = std::string(base::as_string_view(*data)); }); base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, @@ -555,7 +555,7 @@ std::string text; base::MockCallback<PlatformClipboard::RequestDataClosure> got_text; EXPECT_CALL(got_text, Run(_)).WillOnce([&](PlatformClipboard::Data data) { - text = std::string(data->front_as<const char>(), data->size()); + text = std::string(base::as_string_view(*data)); }); clipboard_->RequestClipboardData(ClipboardBuffer::kCopyPaste, kMimeTypeText, got_text.Get());
diff --git a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc index 1ca2005..d1f4e89 100644 --- a/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc +++ b/ui/ozone/platform/wayland/host/wayland_exchange_data_provider.cc
@@ -83,22 +83,28 @@ template <typename StringType> StringType BytesTo(PlatformClipboard::Data bytes) { using ValueType = typename StringType::value_type; - if (bytes->size() % sizeof(ValueType) != 0U) { + const size_t bytes_size = bytes->size(); + const size_t rounded_bytes_size = + bytes_size - (bytes_size % sizeof(ValueType)); + if (bytes_size != rounded_bytes_size) { // This is suspicious. LOG(WARNING) << "Data is possibly truncated, or a wrong conversion is requested."; } - StringType result(bytes->front_as<ValueType>(), - bytes->size() / sizeof(ValueType)); + StringType result; + result.resize(rounded_bytes_size / sizeof(ValueType)); + base::as_writable_byte_span(result).copy_from( + base::span(*bytes).first(rounded_bytes_size)); return result; } void AddString(PlatformClipboard::Data data, OSExchangeDataProvider* provider) { DCHECK(provider); - if (data->data().empty()) + if (data->as_vector().empty()) { return; + } provider->SetString(base::UTF8ToUTF16(BytesTo<std::string>(data))); } @@ -106,8 +112,9 @@ void AddHtml(PlatformClipboard::Data data, OSExchangeDataProvider* provider) { DCHECK(provider); - if (data->data().empty()) + if (data->as_vector().empty()) { return; + } provider->SetHtml(base::UTF8ToUTF16(BytesTo<std::string>(data)), GURL()); } @@ -167,8 +174,9 @@ void AddUrl(PlatformClipboard::Data data, OSExchangeDataProvider* provider) { DCHECK(provider); - if (data->data().empty()) + if (data->as_vector().empty()) { return; + } std::u16string data_as_string16 = BytesTo<std::u16string>(data); @@ -196,8 +204,9 @@ void AddSource(PlatformClipboard::Data data, OSExchangeDataProvider* provider) { DCHECK(provider); - if (data->data().empty()) + if (data->as_vector().empty()) { return; + } std::string source_dte = BytesTo<std::string>(data); provider->SetSource(ConvertJsonToDataTransferEndpoint(source_dte));
diff --git a/ui/ozone/platform/wayland/test/test_selection_device_manager.cc b/ui/ozone/platform/wayland/test/test_selection_device_manager.cc index bcf9cf7..1f95e69 100644 --- a/ui/ozone/platform/wayland/test/test_selection_device_manager.cc +++ b/ui/ozone/platform/wayland/test/test_selection_device_manager.cc
@@ -46,7 +46,7 @@ void WriteDataOnWorkerThread(base::ScopedFD fd, ui::PlatformClipboard::Data data) { - if (!base::WriteFileDescriptor(fd.get(), data->data())) { + if (!base::WriteFileDescriptor(fd.get(), data->as_vector())) { LOG(ERROR) << "Failed to write selection data to clipboard."; } }
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc index e15e955..423c9ccf 100644 --- a/ui/views/controls/tabbed_pane/tabbed_pane.cc +++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/i18n/rtl.h" +#include "base/notreached.h" #include "build/build_config.h" #include "cc/paint/paint_flags.h" #include "third_party/skia/include/core/SkPath.h" @@ -131,10 +132,16 @@ } gfx::Size TabbedPaneTab::CalculatePreferredSize() const { + NOTREACHED_NORETURN() << "Use CalculatePreferredSize(SizeBounds)"; +} + +gfx::Size TabbedPaneTab::CalculatePreferredSize( + const SizeBounds& available_size) const { int width = preferred_title_width_ + GetInsets().width(); if (tabbed_pane_->GetStyle() == TabbedPane::TabStripStyle::kHighlight && - tabbed_pane_->GetOrientation() == TabbedPane::Orientation::kVertical) + tabbed_pane_->GetOrientation() == TabbedPane::Orientation::kVertical) { width = std::max(width, 192); + } return gfx::Size(width, 32); } @@ -143,7 +150,7 @@ // LayoutManager::GetPreferredHeightForWidth by default, but this is not // consistent with the fixed height desired by CalculatePreferredSize, so we // override it and call it manually. - return CalculatePreferredSize().height(); + return CalculatePreferredSize(SizeBounds(w, {})).height(); } void TabbedPaneTab::GetAccessibleNodeData(ui::AXNodeData* data) {
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.h b/ui/views/controls/tabbed_pane/tabbed_pane.h index 48f164c..d0d33b2 100644 --- a/ui/views/controls/tabbed_pane/tabbed_pane.h +++ b/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -176,7 +176,9 @@ void OnMouseEntered(const ui::MouseEvent& event) override; void OnMouseExited(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override; - gfx::Size CalculatePreferredSize() const override; + gfx::Size CalculatePreferredSize() const final; + gfx::Size CalculatePreferredSize( + const SizeBounds& available_size) const override; int GetHeightForWidth(int w) const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
diff --git a/ui/views/examples/multiline_example.cc b/ui/views/examples/multiline_example.cc index af9f8a9..c0c3b890 100644 --- a/ui/views/examples/multiline_example.cc +++ b/ui/views/examples/multiline_example.cc
@@ -86,28 +86,27 @@ render_text_->Draw(canvas); } - gfx::Size CalculatePreferredSize() const override { - // Turn off multiline mode to get the single-line text size, which is the - // preferred size for this view. - render_text_->SetMultiline(false); - gfx::Size size(render_text_->GetContentWidth(), - render_text_->GetStringSize().height()); - size.Enlarge(GetInsets().width(), GetInsets().height()); - render_text_->SetMultiline(true); - return size; - } + gfx::Size CalculatePreferredSize( + const SizeBounds& available_size) const override { + int w = available_size.width().value_or(0); + if (w == 0) { + // Turn off multiline mode to get the single-line text size, which is the + // preferred size for this view. + render_text_->SetMultiline(false); + gfx::Size size(render_text_->GetContentWidth(), + render_text_->GetStringSize().height()); + size.Enlarge(GetInsets().width(), GetInsets().height()); + render_text_->SetMultiline(true); + return size; + } - int GetHeightForWidth(int w) const override { - // TODO(ckocagil): Why does this happen? - if (w == 0) - return View::GetHeightForWidth(w); const gfx::Rect old_rect = render_text_->display_rect(); gfx::Rect rect = old_rect; rect.set_width(w - GetInsets().width()); render_text_->SetDisplayRect(rect); int height = render_text_->GetStringSize().height() + GetInsets().height(); render_text_->SetDisplayRect(old_rect); - return height; + return gfx::Size(w, height); } void OnThemeChanged() override {
diff --git a/ui/views/layout/layout_types.h b/ui/views/layout/layout_types.h index 14e05150..152dc37 100644 --- a/ui/views/layout/layout_types.h +++ b/ui/views/layout/layout_types.h
@@ -62,6 +62,10 @@ return is_bounded() ? std::min(this->value(), value) : value; } + constexpr int value_or(int defaule_value) const { + return is_bounded() ? value() : defaule_value; + } + void operator+=(const SizeBound& rhs); void operator-=(const SizeBound& rhs);
diff --git a/ui/views/test/test_views.cc b/ui/views/test/test_views.cc index c5dd24a8..69ac753 100644 --- a/ui/views/test/test_views.cc +++ b/ui/views/test/test_views.cc
@@ -44,14 +44,16 @@ PreferredSizeChanged(); } -int ProportionallySizedView::GetHeightForWidth(int w) const { - return w * factor_; -} - -gfx::Size ProportionallySizedView::CalculatePreferredSize() const { - if (preferred_width_ >= 0) - return gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_)); - return View::CalculatePreferredSize(); +gfx::Size ProportionallySizedView::CalculatePreferredSize( + const SizeBounds& available_size) const { + if (available_size.width().is_bounded()) { + int w = available_size.width().value(); + return gfx::Size(w, w * factor_); + } else if (preferred_width_ >= 0) { + return gfx::Size(preferred_width_, preferred_width_ * factor_); + } else { + return View::CalculatePreferredSize(available_size); + } } BEGIN_METADATA(ProportionallySizedView)
diff --git a/ui/views/test/test_views.h b/ui/views/test/test_views.h index dfed1df..5f65e72 100644 --- a/ui/views/test/test_views.h +++ b/ui/views/test/test_views.h
@@ -61,8 +61,8 @@ void SetPreferredWidth(int width); - int GetHeightForWidth(int w) const override; - gfx::Size CalculatePreferredSize() const override; + gfx::Size CalculatePreferredSize( + const SizeBounds& available_size) const override; private: // The multiplicative factor between width and height, i.e.
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.html b/ui/webui/resources/cr_components/history_clusters/cluster.html index c80f33e..1650c8ec 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.html +++ b/ui/webui/resources/cr_components/history_clusters/cluster.html
@@ -7,17 +7,14 @@ padding-bottom: var(--cluster-padding-vertical); } - :host-context([chrome-refresh-2023]):host([in-side-panel]) { - --search-query-margin: 4px; - } - :host([in-side-panel]) { --cr-icon-button-margin-start: 8px; + --search-query-margin: 4px; padding-bottom: 0; padding-top: 8px; } - :host-context([chrome-refresh-2023]):host([in-side-panel]) #container { + :host([in-side-panel]) #container { background: var(--color-side-panel-card-background); border-radius: 12px; overflow: hidden; @@ -78,12 +75,8 @@ } :host([in-side-panel]) .timestamp { - font-size: .75rem; /* 12px */ - line-height: calc(5/3); /* 20px */ - } - - :host-context([chrome-refresh-2023]):host([in-side-panel_]) .timestamp { font-size: .6875rem; /* 11px */ + line-height: calc(5/3); /* 20px */ } .debug-info { @@ -94,27 +87,18 @@ display: none; } - :host-context([chrome-refresh-2023]):host([in-side-panel]) #related-searches-divider { + :host([in-side-panel]) #related-searches-divider { display: block; background-color: var(--color-history-clusters-side-panel-divider); height: 1px; margin: 8px 16px; } - :host-context(html:not([chrome-refresh-2023])) #related-searches { - /* Top is a special 8px value. */ - margin: 0 var(--cluster-padding-horizontal) 0; - } - - :host-context(html:not([chrome-refresh-2023])):host([in-side-panel]) #related-searches { - margin: -8px 16px var(--cluster-padding-vertical); - } - - :host-context([chrome-refresh-2023]) #related-searches { + #related-searches { margin: 16px var(--cluster-padding-horizontal) 0px; } - :host-context([chrome-refresh-2023]):host([in-side-panel]) #related-searches { + :host([in-side-panel]) #related-searches { /* 2px left and right margin so related searches don't overlap container * focus indicator. */ margin: 16px 2px; @@ -122,7 +106,7 @@ /*TODO(mfacey): Figure out appropriate non side panel color to show carousel buttons. */ - :host-context([chrome-refresh-2023]):host([in-side-panel]) search-query { + :host([in-side-panel]) search-query { flex-shrink: 0; margin-top: 0; } @@ -131,13 +115,9 @@ margin-inline-end: var(--search-query-margin); } - :host-context([chrome-refresh-2023]):host([in-side-panel]) search-query:first-of-type { + :host([in-side-panel]) search-query:first-of-type { margin-inline-start: 16px; } - - :host-context(html:not([chrome-refresh-2023])) search-query { - margin-top: 8px; - } </style> <div id="container" on-visit-clicked="onVisitClicked_" on-open-all-visits="onOpenAllVisits_"
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.html b/ui/webui/resources/cr_components/history_clusters/clusters.html index 32f5486..f8120017 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.html +++ b/ui/webui/resources/cr_components/history_clusters/clusters.html
@@ -22,10 +22,6 @@ :host([in-side-panel_]) #clusters { min-width: 0; - padding: 8px 0 0; - } - - :host-context([chrome-refresh-2023]):host([in-side-panel_]) #clusters { padding: 0; } @@ -35,10 +31,6 @@ } :host([in-side-panel_]) history-cluster { - border-bottom: 4px solid var(--cr-separator-color); - } - - :host-context([chrome-refresh-2023]):host([in-side-panel_]) history-cluster { border-bottom: none; } @@ -64,26 +56,29 @@ 0 var(--cluster-padding-horizontal) var(--cluster-padding-vertical); } - :host-context([chrome-refresh-2023]):host([in-side-panel_]) #footer { + :host([in-side-panel_]) #footer { padding-top: var(--cluster-padding-vertical); } /*TODO(mfacey): Refactor history clusters side panel to use shadow parts*/ - :host-context([chrome-refresh-2023]):host([in-side-panel_]) cr-dialog { - --cr-dialog-background-color: var(--color-history-clusters-side-panel-dialog-background); - --cr-primary-text-color: var(--color-history-clusters-side-panel-dialog-primary-foreground); - --cr-secondary-text-color: var( - --color-history-clusters-side-panel-dialog-secondary-foreground); + :host([in-side-panel_]) cr-dialog { + --cr-dialog-background-color: + var(--color-history-clusters-side-panel-dialog-background); + --cr-primary-text-color: + var(--color-history-clusters-side-panel-dialog-primary-foreground); + --cr-secondary-text-color: + var(--color-history-clusters-side-panel-dialog-secondary-foreground); --cr-dialog-title-font-size: 16px; --cr-dialog-title-slot-padding-bottom: 8px; font-weight: 500; } -:host-context([chrome-refresh-2023]):host([in-side-panel_]) cr-dialog::part(dialog) { - --scroll-border-color: var(--color-history-clusters-side-panel-dialog-divider); - border-radius: 12px; - box-shadow: var(--cr-elevation-3); -} + :host([in-side-panel_]) cr-dialog::part(dialog) { + --scroll-border-color: + var(--color-history-clusters-side-panel-dialog-divider); + border-radius: 12px; + box-shadow: var(--cr-elevation-3); + } </style> <div id="placeholder" hidden="[[!placeholderText_]]"> [[placeholderText_]]
diff --git a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css b/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css index d25b976..15a9480 100644 --- a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css +++ b/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css
@@ -22,25 +22,17 @@ border: 1px solid var(--border-color); border-radius: calc(var(--pill-height) / 2); box-sizing: border-box; - font-size: 0.875rem; /* 14px */ + font-size: 0.75rem; /* 12px */ height: var(--pill-height); line-height: 1.5; /* 21px */ } -:host-context([chrome-refresh-2023]) .pill { - font-size: 0.75rem; /* 12px */ -} - .pill-icon-start { padding-inline-end: var(--pill-padding-text); padding-inline-start: var(--pill-padding-icon); } .pill-icon-start .icon { - margin-inline-end: 8px; -} - -:host-context([chrome-refresh-2023]) .pill-icon-start .icon { margin-inline-end: 4px; }
diff --git a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html index 66ec96b..d4f0928 100644 --- a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html +++ b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html
@@ -1,10 +1,5 @@ <style include="history-clusters-shared-style cr-icons"> :host { - display: flex; - isolation: isolate; - } - - :host-context([chrome-refresh-2023]) { --cr-icon-button-margin-start: 0px; --gradient-start: 64px; --horizontal-carousel-pagination-button-center: @@ -13,26 +8,29 @@ /* 16px cluster padding - 2px margin */ --horizontal-carousel-pagination-button-margin: 14px; --horizontal-carousel-pagination-button-size: 28px; + + display: flex; + isolation: isolate; position: relative; } - :host-context([chrome-refresh-2023]):host(:hover) .carousel-button-container { + :host(:hover) .carousel-button-container { display: block; } - :host-context([chrome-refresh-2023]):host([show-back-button_]:hover) + :host([show-back-button_]:hover) #carouselContainer { -webkit-mask-image: linear-gradient(to right, transparent var(--horizontal-carousel-pagination-button-center), black var(--gradient-start)); } - :host-context([chrome-refresh-2023]):host([show-forward-button_]:hover) + :host([show-forward-button_]:hover) #carouselContainer { -webkit-mask-image: linear-gradient(to right, black calc(100% - var(--gradient-start)), transparent calc(100% - var(--horizontal-carousel-pagination-button-center))); } - :host-context([chrome-refresh-2023]):host([show-back-button_][show-forward-button_]:hover) + :host([show-back-button_][show-forward-button_]:hover) #carouselContainer { -webkit-mask-image: linear-gradient(to right, transparent var(--horizontal-carousel-pagination-button-center), black var(--gradient-start), @@ -40,7 +38,7 @@ transparent calc(100% - var(--horizontal-carousel-pagination-button-center))); } - :host-context([chrome-refresh-2023]) .carousel-button-container { + .carousel-button-container { --cr-icon-button-size: var(--horizontal-carousel-pagination-button-size); background-color: var(--color-button-background-tonal); border-radius: 50%; @@ -54,32 +52,24 @@ z-index: 1; } - :host-context([chrome-refresh-2023]) #carouselForwardButton { + #carouselForwardButton { right: var(--horizontal-carousel-pagination-button-margin); } - :host-context([chrome-refresh-2023]) #carouselBackButton { + #carouselBackButton { left: var(--horizontal-carousel-pagination-button-margin); } #carouselContainer { display: flex; - flex-wrap: wrap; - min-width: 0 - } - - :host-context([chrome-refresh-2023]) #carouselContainer { flex-wrap: nowrap; - padding: 2px; /* To account for 2px focus outline on pills */ min-width: 0; + padding: 2px; /* To account for 2px focus outline on pills */ overflow-x: hidden; } .hover-layer { display: none; - } - - :host-context([chrome-refresh-2023]) .hover-layer { background: var(--cr-hover-background-color); border-radius: 50%; height: var(--horizontal-carousel-pagination-button-size);
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.css b/ui/webui/resources/cr_components/history_clusters/search_query.css index 790fc298..8330e205 100644 --- a/ui/webui/resources/cr_components/history_clusters/search_query.css +++ b/ui/webui/resources/cr_components/history_clusters/search_query.css
@@ -10,11 +10,6 @@ * #css_wrapper_metadata_end */ :host { - display: block; - min-width: 0; -} - -:host-context([chrome-refresh-2023]):host { --border-color: var(--color-suggestion-chip-border, var(--cr-fallback-color-tonal-outline)); --icon-color: var(--color-suggestion-chip-icon, @@ -22,6 +17,8 @@ --pill-padding-text: 12px; --pill-padding-icon: 8px; --pill-height: 28px; + display: block; + min-width: 0; } a { @@ -30,34 +27,15 @@ display: flex; outline: none; text-decoration: none; -} - -:host-context([chrome-refresh-2023]) a { overflow: hidden; position: relative; } -:host(:hover) a { - background-color: var(--cr-hover-background-color); -} - -:host(:active) a { - background-color: var(--cr-active-background-color); -} - -:host-context([chrome-refresh-2023]):host(:hover) a { - background-color: transparent; -} - -:host-context([chrome-refresh-2023]):host(:active) a { - background-color: transparent; -} - :host-context(.focus-outline-visible) a:focus { box-shadow: inset 0 0 0 2px var(--cr-focus-outline-color); } -:host-context([chrome-refresh-2023].focus-outline-visible) a:focus { +:host-context(.focus-outline-visible) a:focus { --pill-padding-icon: 9px; --pill-padding-text: 13px; border: none; @@ -66,7 +44,7 @@ outline-offset: 0; } -:host-context([chrome-refresh-2023]) span { +span { position: relative; z-index: 1; } @@ -76,19 +54,11 @@ --cr-icon-color: var(--icon-color); --cr-icon-image: url(chrome://resources/images/icon_search.svg); --cr-icon-ripple-margin: 0; - --cr-icon-ripple-size: 20px; -} - -:host-context([chrome-refresh-2023]) .icon { --cr-icon-ripple-size: 16px; --cr-icon-size: 16px; } cr-ripple { - display: none; -} - -:host-context([chrome-refresh-2023]) cr-ripple { --paper-ripple-opacity: 1; color: var(--cr-active-background-color); display: block; @@ -98,7 +68,7 @@ display: none; } -:host-context([chrome-refresh-2023]):host(:hover) #hover-layer { +:host(:hover) #hover-layer { background: var(--cr-hover-background-color); content: ''; display: block;
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.ts b/ui/webui/resources/cr_components/history_clusters/search_query.ts index 930fc71..5211f94 100644 --- a/ui/webui/resources/cr_components/history_clusters/search_query.ts +++ b/ui/webui/resources/cr_components/history_clusters/search_query.ts
@@ -63,10 +63,8 @@ //============================================================================ override firstUpdated() { - if (document.documentElement.hasAttribute('chrome-refresh-2023')) { - this.addEventListener('pointerdown', this.onPointerDown_.bind(this)); - this.addEventListener('pointercancel', this.onPointerCancel_.bind(this)); - } + this.addEventListener('pointerdown', this.onPointerDown_.bind(this)); + this.addEventListener('pointercancel', this.onPointerCancel_.bind(this)); } protected onAuxClick_() {
diff --git a/ui/webui/resources/cr_components/history_clusters/shared_vars.css b/ui/webui/resources/cr_components/history_clusters/shared_vars.css index 102f8cfd..1ed7f21 100644 --- a/ui/webui/resources/cr_components/history_clusters/shared_vars.css +++ b/ui/webui/resources/cr_components/history_clusters/shared_vars.css
@@ -16,7 +16,6 @@ --entity-image-background-color: var(--google-grey-50); --icon-color: var(--google-grey-600); --url-color: var(--google-blue-600); - --side-panel-url-color: var(--google-grey-700); } @media (prefers-color-scheme: dark) { @@ -27,7 +26,6 @@ --entity-image-background-color: var(--google-grey-800); --icon-color: white; --url-color: var(--google-blue-300); - --side-panel-url-color: var(--google-grey-500); } }
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.html b/ui/webui/resources/cr_components/history_clusters/url_visit.html index d7e77ebc..9949888 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.html +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.html
@@ -6,7 +6,7 @@ min-height: 64px; } - :host-context([chrome-refresh-2023]):host([in-side-panel_]) { + :host([in-side-panel_]) { min-height: 48px; } @@ -76,7 +76,7 @@ margin-inline-end: 0; } - :host-context([chrome-refresh-2023]):host([in-side-panel_]) #icon { + :host([in-side-panel_]) #icon { background-color: var(--color-list-item-url-favicon-background, var(--cr-fallback-color-neutral-container)); height: 40px; @@ -121,12 +121,8 @@ } :host([in-side-panel_]) #title { - font-size: .8125rem; /* 13px */ - line-height: calc(20/13); /* 20px */ - } - - :host-context([chrome-refresh-2023]):host([in-side-panel_]) #title { font-size: .75rem; /* 12px */ + line-height: calc(20/13); /* 20px */ font-weight: 500; } @@ -136,14 +132,9 @@ } :host([in-side-panel_]) #url { - color: var(--side-panel-url-color); - font-size: .75rem; /* 12px */ - line-height: calc(5/3); /* 20px */ - } - - :host-context([chrome-refresh-2023]):host([in-side-panel_]) #url { color: var(--color-history-clusters-side-panel-card-secondary-foreground); font-size: .6875rem; /* 11px */ + line-height: calc(5/3); /* 20px */ } #debug-info {
diff --git a/ui/webui/resources/cr_components/history_embeddings/filter_chips.ts b/ui/webui/resources/cr_components/history_embeddings/filter_chips.ts index e0550422..8a80344 100644 --- a/ui/webui/resources/cr_components/history_embeddings/filter_chips.ts +++ b/ui/webui/resources/cr_components/history_embeddings/filter_chips.ts
@@ -64,6 +64,10 @@ static get properties() { return { + timeRangeStart: { + type: Object, + observer: 'onTimeRangeStartChanged_', + }, selectedSuggestion: { type: String, notify: true, @@ -97,6 +101,18 @@ this.showResultsByGroup = !this.showResultsByGroup; } + private onTimeRangeStartChanged_() { + if (this.timeRangeStart?.getTime() === + this.selectedSuggestion?.timeRangeStart.getTime()) { + return; + } + + this.selectedSuggestion = this.suggestions_.find(suggestion => { + return suggestion.timeRangeStart.getTime() === + this.timeRangeStart?.getTime(); + }); + } + private onSuggestionClick_(e: DomRepeatEvent<Suggestion>) { const clickedSuggestion = e.model.item; if (this.isSuggestionSelected_(clickedSuggestion)) {
diff --git a/ui/webui/resources/js/OWNERS b/ui/webui/resources/js/OWNERS deleted file mode 100644 index e69de29..0000000 --- a/ui/webui/resources/js/OWNERS +++ /dev/null
diff --git a/ui/webui/resources/tools/codemods/lit_migration.js b/ui/webui/resources/tools/codemods/lit_migration.js index 245d371..4a1302b 100644 --- a/ui/webui/resources/tools/codemods/lit_migration.js +++ b/ui/webui/resources/tools/codemods/lit_migration.js
@@ -6,8 +6,12 @@ const POLYMER_IMPORT = `import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';`; +const POLYMER_IMPORT_WITH_SCHEME = + `import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';`; const LIT_IMPORT = `import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';`; +const LIT_IMPORT_WITH_SCHEME = + `import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';`; const OLD_GET_TEMPLATE = `static get template() { return getTemplate(); @@ -38,6 +42,7 @@ // Step 1: Replace PolymerElement import. source = source.replace(POLYMER_IMPORT, LIT_IMPORT); + source = source.replace(POLYMER_IMPORT_WITH_SCHEME, LIT_IMPORT_WITH_SCHEME); // Step 2: Replace getTemplate import. const basename = path.basename(file.path, '.ts');
diff --git a/v8 b/v8 index 37e4bb8..ead5ccc 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 37e4bb8df182b508cc2df84abd7ef2bd64a5749e +Subproject commit ead5cccdb1ce2bbdb2cb0b09ec66573fc9e371e3