diff --git a/DEPS b/DEPS index 34efb5d..86d2279 100644 --- a/DEPS +++ b/DEPS
@@ -187,7 +187,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'dd29370cdd4111e8a2099e60d99b2343ae12d49e', + 'angle_revision': '93040c8d0d4a90b9edb9a16993812988ceb50027', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -238,7 +238,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '395a627b8ad8b48dc4119fb6d309d29ec5d5fda0', + 'catapult_revision': '56f8fb61b9d5db9fc96313d1675e7c28920b6e8c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -246,7 +246,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': 'a10679ba4c5862bac9bb3ca30d2172c94417eafa', + 'devtools_frontend_revision': '76336cdd0411308cf1971b723614fb0477046435', # 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. @@ -286,7 +286,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': 'f20c0d7971c6705a99b91d7a0278eabbc5d91195', + 'spv_tools_revision': 'e95fbfb1f509ad7a7fdfb72ac35fe412d72fc4a4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -302,7 +302,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '2b24fab368ae39f1ef9df5cb3c3e756f5173dce1', + 'dawn_revision': 'c00163ba0925a7de0936a0b0c8385e1986ae5a4c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -933,7 +933,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + '638ef84819f8b3cd614dcf63378fe4814aa4cb2a', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '0b66fa3b62cb36a3bc86f5018cf92a5211b27156', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'b5757b95005bbf6b0287096c5b708c5e25645311', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1211,7 +1211,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '6f26bce0b1c4e8ce0e13332f7c0083788def5fdf', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + 'f954babacc6cd535d426d577d1fa0d0932539cb3', + Var('chromium_git') + '/openscreen' + '@' + '31665eb818aaefbb1ad706b0f2a99846125d1321', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '9e97b73e7dd2bfc07745489d728f6a36665c648f', @@ -1228,7 +1228,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '2da86adf0fb8fd64ae2e7ac4cc9eb7b45772a79c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f5a94cc6837a834edde4d65e991c004a7fe99d4b', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1331,7 +1331,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'QBuWB80TzI5JFXtwaZQbr91Ry3Lb0AmRl8kBchm5FY0C', + 'version': 'I91wspV6GMc7l_m-k9v3-ooP-CBrK76OVc3rfnB5T7kC', }, ], 'condition': 'checkout_android', @@ -1458,7 +1458,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '04c1b445019e10e54b96f70403d25cc54215faf3', + Var('webrtc_git') + '/src.git' + '@' + '52e2dbf1c11578414ffb5b155bf97a84b6ad647f', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1533,7 +1533,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b6fff1b9fabd7189a8da4201cadc4dd5ea457a26', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@331b83f6375688a0b157a7ce6c01a37fcd779639', 'condition': 'checkout_src_internal', },
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc index 0fcf3d3..704fe95 100644 --- a/ash/ambient/ambient_controller.cc +++ b/ash/ambient/ambient_controller.cc
@@ -74,6 +74,8 @@ void AmbientController::OnWidgetDestroying(views::Widget* widget) { refresh_timer_.Stop(); + photo_model_.Clear(); + weak_factory_.InvalidateWeakPtrs(); container_view_->GetWidget()->RemoveObserver(this); container_view_ = nullptr; @@ -170,9 +172,9 @@ refresh_interval = base::TimeDelta::FromSeconds(5); } - refresh_timer_.Start( - FROM_HERE, refresh_interval, - base::BindOnce(&AmbientController::RefreshImage, base::Unretained(this))); + refresh_timer_.Start(FROM_HERE, refresh_interval, + base::BindOnce(&AmbientController::RefreshImage, + weak_factory_.GetWeakPtr())); } void AmbientController::GetNextImage() {
diff --git a/ash/ambient/model/photo_model.cc b/ash/ambient/model/photo_model.cc index 29bf8994..8f73254 100644 --- a/ash/ambient/model/photo_model.cc +++ b/ash/ambient/model/photo_model.cc
@@ -54,6 +54,11 @@ NotifyImagesChanged(); } +void PhotoModel::Clear() { + images_.clear(); + current_image_index_ = 0; +} + gfx::ImageSkia PhotoModel::GetPrevImage() const { if (current_image_index_ == 0) return gfx::ImageSkia();
diff --git a/ash/ambient/model/photo_model.h b/ash/ambient/model/photo_model.h index 7a8d5b8f..e41336c0 100644 --- a/ash/ambient/model/photo_model.h +++ b/ash/ambient/model/photo_model.h
@@ -34,6 +34,9 @@ // Add image to local storage. void AddNextImage(const gfx::ImageSkia& image); + // Clear local storage. + void Clear(); + // Get images from local storage. Could be null image. gfx::ImageSkia GetPrevImage() const; gfx::ImageSkia GetCurrImage() const;
diff --git a/ash/public/cpp/ambient/photo_controller.cc b/ash/public/cpp/ambient/photo_controller.cc index 890f7d49..75e8b8a 100644 --- a/ash/public/cpp/ambient/photo_controller.cc +++ b/ash/public/cpp/ambient/photo_controller.cc
@@ -16,13 +16,13 @@ PhotoController::Topic::Topic() = default; -PhotoController::Topic::~Topic() = default; - PhotoController::Topic::Topic(const Topic&) = default; PhotoController::Topic& PhotoController::Topic::operator=(const Topic&) = default; +PhotoController::Topic::~Topic() = default; + // static PhotoController* PhotoController::Get() { return g_photo_controller;
diff --git a/ash/public/cpp/ambient/photo_controller.h b/ash/public/cpp/ambient/photo_controller.h index 1269f6f..deb5a2c 100644 --- a/ash/public/cpp/ambient/photo_controller.h +++ b/ash/public/cpp/ambient/photo_controller.h
@@ -43,10 +43,20 @@ using PhotoDownloadCallback = base::OnceCallback<void(bool success, const gfx::ImageSkia&)>; + using GetSettingsCallback = + base::OnceCallback<void(const base::Optional<int>& topic_source)>; + using UpdateSettingsCallback = base::OnceCallback<void(bool success)>; // Get next image. virtual void GetNextImage(PhotoDownloadCallback callback) = 0; + // Get settings. + virtual void GetSettings(GetSettingsCallback callback) = 0; + + // Update settings. + virtual void UpdateSettings(int topic_source, + UpdateSettingsCallback callback) = 0; + protected: PhotoController(); virtual ~PhotoController();
diff --git a/ash/public/cpp/test/test_photo_controller.cc b/ash/public/cpp/test/test_photo_controller.cc index 13af051..15f51ebf 100644 --- a/ash/public/cpp/test/test_photo_controller.cc +++ b/ash/public/cpp/test/test_photo_controller.cc
@@ -22,4 +22,14 @@ std::move(callback).Run(/*success=*/true, image); } +void TestPhotoController::GetSettings(GetSettingsCallback callback) { + // 0 is the enum number for Google Photos. + std::move(callback).Run(/*topic_source=*/0); +} + +void TestPhotoController::UpdateSettings(int topic_source, + UpdateSettingsCallback callback) { + std::move(callback).Run(/*success=*/true); +} + } // namespace ash
diff --git a/ash/public/cpp/test/test_photo_controller.h b/ash/public/cpp/test/test_photo_controller.h index cc0e2df..5beadf0 100644 --- a/ash/public/cpp/test/test_photo_controller.h +++ b/ash/public/cpp/test/test_photo_controller.h
@@ -19,6 +19,9 @@ // PhotoController: void GetNextImage(PhotoController::PhotoDownloadCallback callback) override; + void GetSettings(GetSettingsCallback callback) override; + void UpdateSettings(int topic_source, + UpdateSettingsCallback callback) override; }; } // namespace ash
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index 74081ed..ed626046 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -2105,9 +2105,17 @@ gfx::RoundedCornersF ScrollableShelfView::CalculateShelfContainerRoundedCorners() const { - if (!chromeos::switches::ShouldShowShelfHotseat() || - !Shell::Get()->IsInTabletMode()) + // This function may access TabletModeController during destruction of + // Hotseat. However, TabletModeController is destructed before Hotseat. So + // check the pointer explicitly here. + // TODO(andrewxu): reorder the destruction order in Shell::~Shell then remove + // the explicit check. + const bool is_in_tablet_mode = + Shell::Get()->tablet_mode_controller() && Shell::Get()->IsInTabletMode(); + + if (!chromeos::switches::ShouldShowShelfHotseat() || !is_in_tablet_mode) { return gfx::RoundedCornersF(); + } const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment(); const float radius = (is_horizontal_alignment ? height() : width()) / 2.f;
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 0df2b57..f63f5f3 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -68,6 +68,9 @@ } } + # Our build rules support only KitKat+. + default_min_sdk_version = 19 + if (!defined(default_android_ndk_root)) { default_android_ndk_root = "//third_party/android_ndk" default_android_ndk_version = "r20" @@ -232,7 +235,7 @@ java_warnings_as_errors = !is_java_debug # Desugar with D8 rather than Desugar tool. - desugar_with_d8 = false + desugar_with_d8 = is_java_debug } # Path to where selected build variables are written to.
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 79ffa1a..53137fd0 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -858,7 +858,7 @@ lint_suppressions_file = "//build/android/lint/suppressions.xml" } - _min_sdk_version = 19 + _min_sdk_version = default_min_sdk_version if (defined(invoker.min_sdk_version)) { _min_sdk_version = invoker.min_sdk_version } @@ -1146,6 +1146,10 @@ # disable_incremental: Disable incremental dexing. template("dex") { assert(defined(invoker.output)) + _min_sdk_version = default_min_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } _proguard_enabled = defined(invoker.proguard_enabled) && invoker.proguard_enabled @@ -1153,15 +1157,20 @@ _proguard_enabled && !defined(invoker.proguard_jar_path) _enable_multidex = !defined(invoker.enable_multidex) || invoker.enable_multidex - _enable_main_dex_list = - _enable_multidex && - (!defined(invoker.min_sdk_version) || invoker.min_sdk_version < 21) + _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21 if (!_enable_main_dex_list) { if (defined(invoker.negative_main_dex_globs)) { not_needed(invoker, [ "negative_main_dex_globs" ]) } } + # When using d8 to desugar, the dex merge step must not be set to a higher + # minSdkVersion than the libraries in order for the proper backported + # methods to be included. + if (invoker.enable_desugar && defined(invoker.input_dex_filearg)) { + _min_sdk_version = default_min_sdk_version + } + assert(!_proguard_enabled || !(defined(invoker.input_dex_filearg) || defined(invoker.input_classes_filearg) || defined(invoker.input_class_jars)), @@ -1214,6 +1223,7 @@ args = [ "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", "--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)", + "--min-api=$_min_sdk_version", ] if (defined(invoker.proguard_args)) { args += invoker.proguard_args @@ -1232,13 +1242,6 @@ args += [ "--apply-mapping=$_rebased_apply_mapping_path" ] } - if (defined(invoker.min_sdk_version)) { - args += [ - "--min-api", - "${invoker.min_sdk_version}", - ] - } - if (_proguarding_with_r8 && _enable_main_dex_list) { if (defined(invoker.extra_main_dex_proguard_config)) { args += [ @@ -1368,6 +1371,7 @@ rebase_path(depfile, root_build_dir), "--output", rebase_path(outputs[0], root_build_dir), + "--min-api=$_min_sdk_version", ] if (_proguard_enabled) { @@ -1441,13 +1445,6 @@ args += [ "--release" ] } - if (defined(invoker.min_sdk_version)) { - args += [ - "--min-api", - "${invoker.min_sdk_version}", - ] - } - if (invoker.enable_desugar) { args += [ "--desugar",
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index c7414ad..f4af27f 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1363,7 +1363,7 @@ android_manifest = "//build/android/AndroidManifest.xml" } arsc_output = _resource_arsc_output - min_sdk_version = 19 + min_sdk_version = default_min_sdk_version target_sdk_version = 23 } @@ -1852,7 +1852,7 @@ supports_android = true requires_android = true if (!defined(invoker.min_sdk_version)) { - min_sdk_version = 19 + min_sdk_version = default_min_sdk_version } if (!defined(jar_excluded_patterns)) { @@ -2104,7 +2104,7 @@ # static_library_provider target will provide the dex file(s) for this # target. # min_sdk_version: The minimum Android SDK version this target supports. - # Optional, default 19. + # Optional, default $default_min_sdk_version. # target_sdk_version: The target Android SDK version for this target. # Optional, default 23. # max_sdk_version: The maximum Android SDK version this target supports. @@ -2137,7 +2137,7 @@ _build_config = "$target_gen_dir/$target_name.build_config" _build_config_target = "$target_name$build_config_target_suffix" - _min_sdk_version = 19 + _min_sdk_version = default_min_sdk_version _target_sdk_version = 23 if (defined(invoker.min_sdk_version)) { _min_sdk_version = invoker.min_sdk_version
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni index 3d45f12..1afbfa4 100644 --- a/build/config/fuchsia/generate_runner_scripts.gni +++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -81,12 +81,17 @@ } wrapper_script = generated_run_pkg_script_path - deps = [ invoker.package ] - if (defined(invoker.deps)) { - deps += invoker.deps - } + data_deps = [ + invoker.package, - data_deps = [ invoker.package ] + # Runner scripts require access to "ids.txt" for symbolization, and to + # the "package" from which to get the name & version to deploy, which + # are outputs of the archive manifest generation action. + invoker.package + "__archive-manifest", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } # Declares the files that are needed for test execution on the # swarming test client. @@ -133,7 +138,10 @@ package_dep_target = package_dep[0] package_dep_name = package_dep[1] - deps += [ package_dep_target ] + data_deps += [ + package_dep_target, + package_dep_target + "__archive-manifest", + ] package_dep_path = rebase_path( get_label_info(package_dep_target, "target_gen_dir") + "/" + package_dep_name + "/" + package_dep_name + ".far", @@ -178,9 +186,9 @@ executable = rebase_path("//build/fuchsia/deploy_to_amber_repo.py") wrapper_script = generated_install_pkg_script_path - deps = [ invoker.package ] - if (defined(invoker.deps)) { - deps += invoker.deps + data_deps = [ invoker.package ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps } # Build a list of all packages to install, and pass the list to the runner @@ -191,7 +199,7 @@ package_dep_target = package_dep[0] package_dep_name = package_dep[1] - deps += [ package_dep_target ] + data_deps += [ package_dep_target ] package_dep_path = rebase_path( get_label_info(package_dep_target, "target_gen_dir") + "/" + package_dep_name + "/" + package_dep_name + ".far",
diff --git a/build/config/fuchsia/package.gni b/build/config/fuchsia/package.gni index 8fe34fe0..3324738 100644 --- a/build/config/fuchsia/package.gni +++ b/build/config/fuchsia/package.gni
@@ -2,8 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/sysroot.gni") +import("//third_party/fuchsia-sdk/sdk/build/component.gni") +import("//third_party/fuchsia-sdk/sdk/build/package.gni") +# DEPRECATED: Use the Fuchsia SDK's fuchsia_component() and fuchsia_package() +# templates directly, in new code. +# # Creates a Fuchsia .far package file containing a Fuchsia component. # # Parameters are: @@ -28,210 +32,97 @@ # # TODO(https://crbug.com/1050703): Migrate consumers to GN SDK equivalents. template("cr_fuchsia_package") { - pkg = { - forward_variables_from(invoker, "*") + assert(defined(invoker.binary)) - if (defined(package_name_override)) { - package_name = package_name_override - } else { - package_name = invoker.target_name - } + if (defined(invoker.package_name_override)) { + _package_name = invoker.package_name_override + } else { + _package_name = invoker.target_name + } - if (defined(archive_name_override)) { - archive_filename = archive_name_override - } else { - archive_filename = package_name - } + _package_contents = [ invoker.binary ] + if (defined(invoker.deps)) { + _package_contents += invoker.deps + } - if (!defined(manifest)) { + _component_target = target_name + "__cr-component" + _package_components = [ ":${_component_target}" ] + + # Declare the primary component for this package. + fuchsia_component(_component_target) { + forward_variables_from(invoker, + [ + #"data", + "testonly", + ]) + + if (!defined(invoker.manifest)) { assert(testonly == true) # TODO(1019938): switch the default to tests.cmx which doesn't request # the deprecated-ambient-replace-as-executable feature. - manifest = "//build/config/fuchsia/tests-with-exec.cmx" + manifest_fragment = "//build/config/fuchsia/tests-with-exec.cmx" + } else { + manifest_fragment = invoker.manifest + } + + manifest_fragment_data = read_file(manifest_fragment, "json") + if (!defined(manifest_fragment_data.program)) { + manifest_fragment_data.program = { + binary = get_label_info(invoker.binary, "name") + } + } + manifest = "$target_out_dir/" + target_name + "__component-manifest.cmx" + write_file(manifest, manifest_fragment_data, "json") + + if (defined(invoker.component_name_override)) { + manifest_output_name = "${invoker.component_name_override}" + } else { + manifest_output_name = "${_package_name}" + } + + data_deps = _package_contents + } + + # Bundle manifests providing additional entrypoints into the package. + if (defined(invoker.additional_manifests)) { + foreach(filename, invoker.additional_manifests) { + _additional_component_target = target_name + "_" + filename + _package_components += [ ":${_additional_component_target}" ] + fuchsia_component(_additional_component_target) { + forward_variables_from(invoker, [ "testonly" ]) + data_deps = _package_contents + manifest = filename + } } } - assert(defined(pkg.binary)) - _pm_tool_path = "//third_party/fuchsia-sdk/sdk/tools/pm" - - _pkg_out_dir = "${target_gen_dir}/${pkg.archive_filename}" - _runtime_deps_file = "$_pkg_out_dir/${pkg.archive_filename}.runtime_deps" - _archive_manifest = "$_pkg_out_dir/${pkg.archive_filename}.archive_manifest" - _build_ids_file = "$_pkg_out_dir/ids.txt" - _meta_far_file = "$_pkg_out_dir/meta.far" - _combined_far_file = "$_pkg_out_dir/${pkg.package_name}-0.far" - _final_far_file = "$_pkg_out_dir/${pkg.archive_filename}.far" - _package_info_path = "$_pkg_out_dir/package" - - if (defined(pkg.component_name_override)) { - _generated_cmx = "$_pkg_out_dir/${pkg.component_name_override}.cmx" + # Generate a Fuchsia ARchive (FAR) of the requested name. + if (defined(invoker.archive_name_override)) { + _archive_name = invoker.archive_name_override } else { - _generated_cmx = "$_pkg_out_dir/${pkg.package_name}.cmx" + _archive_name = _package_name } - _write_manifest_target = "${pkg.package_name}__write_manifest" - _package_target = "${pkg.package_name}__pkg" - _bundle_target = "${pkg.package_name}__bundle" + if (_archive_name != _package_name) { + _archive_target = target_name + "__cr-archive" - # Generates a manifest file based on the GN runtime deps - # suitable for "pm" tool consumption. - action(_write_manifest_target) { - _depfile = "${target_gen_dir}/${target_name}_stamp.d" - - forward_variables_from(invoker, - [ - "data", - "deps", - "testonly", - ]) - - script = "//build/config/fuchsia/prepare_package_inputs.py" - - inputs = [ - _runtime_deps_file, - pkg.manifest, - ] - - outputs = [ - _archive_manifest, - _build_ids_file, - _generated_cmx, - ] - - if (!defined(deps)) { - deps = [] + copy(target_name) { + deps = [ ":${_archive_target}" ] + _pkg_out_dir = "${target_gen_dir}/${_package_name}" + sources = [ "${_pkg_out_dir}/${_package_name}.far" ] + outputs = [ "${_pkg_out_dir}/${_archive_name}.far" ] } - deps += [ pkg.binary ] - data_deps = deps - - # Use a depfile to trigger package rebuilds if any of the files (static - # assets, shared libraries, etc.) included by the package have changed. - depfile = _depfile - - args = [ - "--root-dir", - rebase_path("//", root_build_dir), - "--out-dir", - rebase_path(root_out_dir, root_build_dir), - "--app-name", - pkg.package_name, - "--app-filename", - get_label_info(pkg.binary, "name"), - "--manifest-input-path", - rebase_path(pkg.manifest, root_build_dir), - "--runtime-deps-file", - rebase_path(_runtime_deps_file, root_build_dir), - "--depfile-path", - rebase_path(_depfile, root_build_dir), - "--package-manifest-path", - rebase_path(_archive_manifest, root_build_dir), - "--component-manifest-path", - rebase_path(_generated_cmx, root_build_dir), - "--build-ids-file", - rebase_path(_build_ids_file, root_build_dir), - ] - - if (defined(pkg.excluded_files)) { - foreach(filename, pkg.excluded_files) { - args += [ - "--exclude-file", - filename, - ] - } - } - - if (defined(pkg.additional_manifests)) { - foreach(filename, pkg.additional_manifests) { - args += [ - "--additional-manifest", - rebase_path(filename), - ] - } - } - - write_runtime_deps = _runtime_deps_file + } else { + _archive_target = target_name } - # Creates a signed Fuchsia metadata package. - action(_package_target) { + fuchsia_package(_archive_target) { forward_variables_from(invoker, [ "testonly" ]) - - script = "//build/gn_run_binary.py" - - deps = [ ":$_write_manifest_target" ] - - inputs = [ - # Depend on the SDK hash, to ensure rebuild if the SDK tools change. - "//third_party/fuchsia-sdk/sdk/.hash", - ] - - if (defined(pkg.additional_manifests)) { - inputs += pkg.additional_manifests + package_name = _package_name + if (defined(invoker.excluded_files)) { + excluded_files = invoker.excluded_files } - - outputs = [ _meta_far_file ] - - args = [ - rebase_path(_pm_tool_path, root_build_dir), - "-o", - rebase_path(_pkg_out_dir, root_build_dir), - "-m", - rebase_path(_archive_manifest, root_build_dir), - "build", - ] - } - - # Creates a package containing the metadata archive and blob data. - action(_bundle_target) { - forward_variables_from(invoker, [ "testonly" ]) - - script = "//build/gn_run_binary.py" - - deps = [ - ":$_package_target", - ":$_write_manifest_target", - ] - - inputs = [ - # Depend on the SDK hash, to ensure rebuild if the SDK tools change. - "//third_party/fuchsia-sdk/sdk/.hash", - _meta_far_file, - _archive_manifest, - ] - - outputs = [ _combined_far_file ] - - args = [ - rebase_path(_pm_tool_path, root_build_dir), - "-o", - rebase_path(_pkg_out_dir, root_build_dir), - "-m", - rebase_path(_archive_manifest, root_build_dir), - "archive", - ] - } - - # Copies the archive to a well-known path. - # TODO(kmarshall): Use a 'pm' output flag to write directly to the desired - # file path instead. - copy(target_name) { - forward_variables_from(invoker, [ "testonly" ]) - - # Allows dependent targets to make use of "ids.txt". - public_deps = [ ":$_write_manifest_target" ] - - deps = [ ":$_bundle_target" ] - - data = [ - _final_far_file, - - # Files specified here so that they can be read by isolated testbots. - _package_info_path, - _build_ids_file, - ] - - sources = [ _combined_far_file ] - outputs = [ _final_far_file ] + deps = _package_components } }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 83c234d..77cf61c 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200402.2.2 \ No newline at end of file +0.20200403.0.1 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index b486afd..51acab0f 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200402.2.3 \ No newline at end of file +0.20200402.3.1 \ No newline at end of file
diff --git a/build/fuchsia/run_package.py b/build/fuchsia/run_package.py index cdb3b71..8e18a57 100644 --- a/build/fuchsia/run_package.py +++ b/build/fuchsia/run_package.py
@@ -20,7 +20,6 @@ import threading import uuid -from symbolizer import RunSymbolizer from symbolizer import SymbolizerFilter FAR = common.GetHostToolPathFromPlatform('far') @@ -37,36 +36,6 @@ stdout=subprocess.PIPE) -def _BuildIdsPaths(package_paths): - """Generate build ids paths for symbolizer processes.""" - build_ids_paths = map( - lambda package_path: os.path.join( - os.path.dirname(package_path), 'ids.txt'), - package_paths) - return build_ids_paths - - -def StartSystemLogReader(target, package_paths, isolated_outputs_dir): - """Start a system log reader as a long-running SSH task. - - Returns listener and symbolizer popen objects so that the caller can control - the popen process lifetimes.""" - logging.info('Starting system log reader') - - listener_proc = target.RunCommandPiped(['log_listener'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - listener_log_path = os.path.join(isolated_outputs_dir, 'log_listener_log') - build_ids_paths = _BuildIdsPaths(package_paths) - listener_log = open(listener_log_path,'w', buffering=1) - symbolizer_proc = RunSymbolizer(listener_proc.stdout, - listener_log, - build_ids_paths) - - return (listener_proc, symbolizer_proc) - - class MergedInputStream(object): """Merges a number of input streams into a UNIX pipe on a dedicated thread. Terminates when the file descriptor of the primary stream (the first in @@ -225,7 +194,10 @@ output_stream = process.stdout # Run the log data through the symbolizer process. - build_ids_paths = _BuildIdsPaths(package_paths) + build_ids_paths = map( + lambda package_path: os.path.join( + os.path.dirname(package_path), 'ids.txt'), + package_paths) output_stream = SymbolizerFilter(output_stream, build_ids_paths) for next_line in output_stream:
diff --git a/build/fuchsia/test_runner.py b/build/fuchsia/test_runner.py index c315af7..02fb07f 100755 --- a/build/fuchsia/test_runner.py +++ b/build/fuchsia/test_runner.py
@@ -18,7 +18,7 @@ from common_args import AddCommonArgs, ConfigureLogging, GetDeploymentTargetForArgs from net_test_server import SetupTestServer -from run_package import RunPackage, RunPackageArgs, StartSystemLogReader +from run_package import RunPackage, RunPackageArgs DEFAULT_TEST_SERVER_CONCURRENCY = 4 @@ -146,12 +146,6 @@ for_package=args.package_name) child_args.append('--test-launcher-filter-file=' + TEST_FILTER_PATH) - isolated_outputs_dir = os.path.dirname(args.system_log_file) - if os.path.isdir(isolated_outputs_dir): - # Store logging popen objects so that they live as long as the target. - system_log_procs = StartSystemLogReader(target, args.package, - isolated_outputs_dir) - test_server = None if args.enable_test_server: assert test_concurrency
diff --git a/chrome/MAJOR_BRANCH_DATE b/chrome/MAJOR_BRANCH_DATE index ec637d7c..16c8984f 100644 --- a/chrome/MAJOR_BRANCH_DATE +++ b/chrome/MAJOR_BRANCH_DATE
@@ -1 +1 @@ -MAJOR_BRANCH_DATE=2020-03-13 +MAJOR_BRANCH_DATE=2020-04-03
diff --git a/chrome/VERSION b/chrome/VERSION index 012d275..a2444aa 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ -MAJOR=83 +MAJOR=84 MINOR=0 -BUILD=4103 +BUILD=4104 PATCH=0
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 5632c4a..011f399 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -174,6 +174,7 @@ "junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java", "junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java", "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java", + "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/DialogManagerTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/EnsureAsyncPostingRule.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragmentTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 5c4a3862..89fa08d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -209,11 +209,6 @@ */ static final int NO_TOOLBAR_LAYOUT = -1; - /** - * Timeout in ms for reading PartnerBrowserCustomizations provider. - */ - private static final int PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS = 10000; - private C mComponent; protected ObservableSupplierImpl<TabModelSelector> mTabModelSelectorSupplier = @@ -1099,8 +1094,7 @@ if (mPartnerBrowserRefreshNeeded) { mPartnerBrowserRefreshNeeded = false; - PartnerBrowserCustomizations.getInstance().initializeAsync( - getApplicationContext(), PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS); + PartnerBrowserCustomizations.getInstance().initializeAsync(getApplicationContext()); PartnerBrowserCustomizations.getInstance().setOnInitializeAsyncFinished(() -> { if (PartnerBrowserCustomizations.isIncognitoDisabled()) { terminateIncognitoSession();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java index 2d99f5d..1064bcb3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -68,12 +68,6 @@ private static final String TAG = "ActivitiyDispatcher"; - /** - * Timeout in ms for reading PartnerBrowserCustomizations provider. We do not trust third party - * provider by default. - */ - private static final int PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS = 10000; - private final Activity mActivity; private final Intent mIntent; private final boolean mIsCustomTabIntent; @@ -151,7 +145,7 @@ // We want to initialize early because when there are no tabs to restore, we should possibly // show homepage, which might require reading PartnerBrowserCustomizations provider. PartnerBrowserCustomizations.getInstance().initializeAsync( - mActivity.getApplicationContext(), PARTNER_BROWSER_CUSTOMIZATIONS_TIMEOUT_MS); + mActivity.getApplicationContext()); int tabId = IntentUtils.safeGetIntExtra( mIntent, IntentHandler.TabOpenType.BRING_TAB_TO_FRONT_STRING, Tab.INVALID_TAB_ID);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java index 3bd4263..56f44dd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
@@ -12,6 +12,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.AsyncTask; import org.chromium.chrome.browser.AppHooks; +import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; import org.chromium.ui.base.ViewUtils; import java.util.HashSet; @@ -57,6 +58,7 @@ @GuardedBy("mProgressLock") private boolean mFaviconsFetchedFromServer; private boolean mFinishedReading; + private boolean mFinishedResolvingBrowserCustomizations; /** * Observer for listeners to receive updates when changes are made to the favicon cache. @@ -90,12 +92,23 @@ /** * Creates the instance of the reader. * @param context A Context object. + * @param browserCustomizations Provides status of partner customizations. */ - public PartnerBookmarksReader(Context context) { + public PartnerBookmarksReader( + Context context, PartnerBrowserCustomizations browserCustomizations) { mContext = context; mNativePartnerBookmarksReader = PartnerBookmarksReaderJni.get().init(PartnerBookmarksReader.this); - initializeAndDisableEditingIfNecessary(); + if (!browserCustomizations.isInitialized()) { + browserCustomizations.initializeAsync(context); + } + browserCustomizations.setOnInitializeAsyncFinished(() -> { + if (browserCustomizations.isBookmarksEditingDisabled()) { + PartnerBookmarksReaderJni.get().disablePartnerBookmarksEditing(); + } + mFinishedResolvingBrowserCustomizations = true; + maybeMarkCreationComplete(); + }); } /** @@ -159,9 +172,7 @@ } mFaviconThrottle.onFaviconFetched(url, result); --mNumFaviconsInProgress; - if (mNumFaviconsInProgress == 0 && mFinishedReading) { - shutDown(); - } + if (canShutdown()) shutDown(); } } @@ -183,14 +194,23 @@ * down the bookmark reader. */ protected void onBookmarksRead() { + mFinishedReading = true; + maybeMarkCreationComplete(); + synchronized (mProgressLock) { + if (canShutdown()) shutDown(); + } + } + + private void maybeMarkCreationComplete() { + if (!mFinishedReading || !mFinishedResolvingBrowserCustomizations) return; PartnerBookmarksReaderJni.get().partnerBookmarksCreationComplete( mNativePartnerBookmarksReader, PartnerBookmarksReader.this); - mFinishedReading = true; - synchronized (mProgressLock) { - if (mNumFaviconsInProgress == 0) { - shutDown(); - } - } + } + + @GuardedBy("mProgressLock") + private boolean canShutdown() { + return mNumFaviconsInProgress == 0 && mFinishedReading + && mFinishedResolvingBrowserCustomizations; } /** @@ -357,19 +377,6 @@ } } - /** - * Disables partner bookmarks editing. - */ - public static void disablePartnerBookmarksEditing() { - sForceDisableEditing = true; - if (sInitialized) PartnerBookmarksReaderJni.get().disablePartnerBookmarksEditing(); - } - - private static void initializeAndDisableEditingIfNecessary() { - sInitialized = true; - if (sForceDisableEditing) disablePartnerBookmarksEditing(); - } - @NativeMethods interface Natives { long init(PartnerBookmarksReader caller);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java index f356de4..819eaf3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -8,6 +8,7 @@ import android.content.pm.ApplicationInfo; import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; /** * The Java counterpart for the C++ partner bookmarks shim. @@ -30,7 +31,8 @@ if (sIsReadingAttempted) return; sIsReadingAttempted = true; - PartnerBookmarksReader reader = new PartnerBookmarksReader(context); + PartnerBookmarksReader reader = + new PartnerBookmarksReader(context, PartnerBrowserCustomizations.getInstance()); boolean systemOrPreStable = (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 1
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java index bae1d5a..ced20b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -24,7 +24,6 @@ import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.ntp.NewTabPage; -import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -39,6 +38,9 @@ private static final String TAG = "PartnerCustomize"; private static final String PROVIDER_AUTHORITY = "com.android.partnerbrowsercustomizations"; + /** Default timeout in ms for reading PartnerBrowserCustomizations provider. */ + private static final int DEFAULT_TIMEOUT_MS = 10_000; + private static final int HOMEPAGE_URL_MAX_LENGTH = 1000; // Private homepage structure. @VisibleForTesting @@ -211,8 +213,7 @@ /** * @return Whether partner bookmarks editing is disabled by the partner. */ - @VisibleForTesting - boolean isBookmarksEditingDisabled() { + public boolean isBookmarksEditingDisabled() { return mBookmarksEditingDisabled; } @@ -255,14 +256,23 @@ * Constructs an async task that reads PartnerBrowserCustomization provider. * * @param context The current application context. + */ + public void initializeAsync(final Context context) { + initializeAsync(context, DEFAULT_TIMEOUT_MS); + } + + /** + * Constructs an async task that reads PartnerBrowserCustomization provider. + * + * @param context The current application context. * @param timeoutMs If initializing takes more than this time, cancels it. The unit is ms. */ - public void initializeAsync(final Context context, long timeoutMs) { + @VisibleForTesting + void initializeAsync(final Context context, long timeoutMs) { mIsInitialized = false; Provider provider = AppHooks.get().getCustomizationProvider(); // Setup an initializing async task. final AsyncTask<Void> initializeAsyncTask = new AsyncTask<Void>() { - private boolean mDisablePartnerBookmarksShim; private boolean mHomepageUriChanged; private void refreshHomepage() { @@ -290,13 +300,7 @@ private void refreshBookmarksEditingDisabled() { try { - boolean disabled = provider.isBookmarksEditingDisabled(); - // Only need to disable it once. - if (disabled != mBookmarksEditingDisabled) { - assert disabled; - mDisablePartnerBookmarksShim = true; - } - mBookmarksEditingDisabled = disabled; + mBookmarksEditingDisabled = provider.isBookmarksEditingDisabled(); } catch (Exception e) { Log.w(TAG, "Partner disable bookmarks editing read failed : ", e); } @@ -355,11 +359,6 @@ if (mHomepageUriChanged && mListener != null) { mListener.onHomepageUpdate(); } - - // Disable partner bookmarks editing if necessary. - if (mDisablePartnerBookmarksShim) { - PartnerBookmarksReader.disablePartnerBookmarksEditing(); - } } };
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java new file mode 100644 index 0000000..84f6226 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
@@ -0,0 +1,170 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.partnerbookmarks; + +import android.content.Context; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; + +/** + * Unit tests for PartnerBookmarksReader. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class PartnerBookmarksReaderTest { + @Rule + public JniMocker mocker = new JniMocker(); + + @Mock + Context mContextMock; + + @Mock + PartnerBookmarksReader.Natives mJniMock; + + @Mock + PartnerBrowserCustomizations mBrowserCustomizations; + + @Captor + ArgumentCaptor<Runnable> mBrowserCustomizationsInitCallback; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mocker.mock(PartnerBookmarksReaderJni.TEST_HOOKS, mJniMock); + Mockito.doNothing() + .when(mBrowserCustomizations) + .setOnInitializeAsyncFinished(mBrowserCustomizationsInitCallback.capture()); + } + + @Test + public void partnerBrowserCustomizations_BookmarkEditingDisabled_AlreadyInitialized() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + + Mockito.verify(mBrowserCustomizations, Mockito.never()).initializeAsync(mContextMock); + + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(true); + mBrowserCustomizationsInitCallback.getValue().run(); + Mockito.verify(mJniMock).disablePartnerBookmarksEditing(); + } + + @Test + public void partnerBrowserCustomizations_BookmarkEditingDisabled_NotAlreadyInitialized() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(false); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + + Mockito.verify(mBrowserCustomizations).initializeAsync(mContextMock); + + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(true); + mBrowserCustomizationsInitCallback.getValue().run(); + Mockito.verify(mJniMock).disablePartnerBookmarksEditing(); + } + + @Test + public void partnerBrowserCustomizations_BookmarkEditingAllowed_AlreadyInitialized() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + + Mockito.verify(mBrowserCustomizations, Mockito.never()).initializeAsync(mContextMock); + + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false); + mBrowserCustomizationsInitCallback.getValue().run(); + Mockito.verify(mJniMock, Mockito.never()).disablePartnerBookmarksEditing(); + } + + @Test + public void partnerBrowserCustomizations_BookmarkEditingAllowed_NotAlreadyInitialized() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(false); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + + Mockito.verify(mBrowserCustomizations).initializeAsync(mContextMock); + + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false); + mBrowserCustomizationsInitCallback.getValue().run(); + Mockito.verify(mJniMock, Mockito.never()).disablePartnerBookmarksEditing(); + } + + @Test + public void partnerBookmarksCreationComplete_NotCalledWithoutBrowserCustomizations() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + reader.onBookmarksRead(); + + Mockito.verify(mJniMock, Mockito.never()) + .partnerBookmarksCreationComplete(Mockito.anyLong(), Mockito.any()); + } + + @Test + public void partnerBookmarksCreationComplete_NotCalledWithoutBookmarksRead() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false); + mBrowserCustomizationsInitCallback.getValue().run(); + + Mockito.verify(mJniMock, Mockito.never()) + .partnerBookmarksCreationComplete(Mockito.anyLong(), Mockito.any()); + } + + @Test + public void partnerBookmarksCreationComplete_Called_WithCustomizationsFirstThenBookmarks() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false); + mBrowserCustomizationsInitCallback.getValue().run(); + reader.onBookmarksRead(); + + Mockito.verify(mJniMock).partnerBookmarksCreationComplete( + Mockito.anyLong(), Mockito.eq(reader)); + } + + @Test + public void partnerBookmarksCreationComplete_Called_WithBookmarksFirstThenCustomizations() { + Mockito.when(mBrowserCustomizations.isInitialized()).thenReturn(true); + + @SuppressWarnings("unused") + PartnerBookmarksReader reader = + new PartnerBookmarksReader(mContextMock, mBrowserCustomizations); + Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false); + reader.onBookmarksRead(); + mBrowserCustomizationsInitCallback.getValue().run(); + + Mockito.verify(mJniMock).partnerBookmarksCreationComplete( + Mockito.anyLong(), Mockito.eq(reader)); + } +}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index f04a106a..45fe507 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -670,7 +670,7 @@ OK </message> <message name="IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE" desc="The title of the dialog that is shown when demo mode setup is in progress."> - Starting demo mode + Starting Demo Mode </message> <message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_TITLE" desc="The title of the dialog that is shown when demo mode setup failed."> Couldn't start demo mode @@ -678,6 +678,13 @@ <message name="IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL" desc="The label of the button that is shown on error screen and that retries demo mode setup with the previously chosen configuration."> OK </message> + <!-- Demo setup progress steps --> + <message name="IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD" desc="List item shown when demo resources are being downloaded"> + Downloading Resources + </message> + <message name="IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL" desc="List item shown when enterprise enrolling for demo mode"> + Enrolling in Demo Mode + </message> <!-- Demo setup flow errors --> <message name="IDS_DEMO_SETUP_OFFLINE_POLICY_ERROR" desc="Error message shown on demo setup screen when loading or parsing offline policy failed."> Could not read offline demo mode policy.
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE.png.sha1 new file mode 100644 index 0000000..54f698c6 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_SCREEN_TITLE.png.sha1
@@ -0,0 +1 @@ +4c1599982a05093bbcbeec264265b8d32f870e53 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD.png.sha1 new file mode 100644 index 0000000..54f698c6 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD.png.sha1
@@ -0,0 +1 @@ +4c1599982a05093bbcbeec264265b8d32f870e53 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL.png.sha1 new file mode 100644 index 0000000..54f698c6 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL.png.sha1
@@ -0,0 +1 @@ +4c1599982a05093bbcbeec264265b8d32f870e53 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 6527f9c..a9eb75c 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -738,6 +738,12 @@ <message name="IDS_SETTINGS_ACCOUNT_MANAGER_PRIMARY_ACCOUNT_TOOLTIP" desc="Tooltip for the primary account in accounts list in Settings describing how to sign out."> To sign out of the primary account on this device, click the time on your screen. In the menu that appears, click "Sign out". </message> + <message name="IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP" desc="Tooltip for the primary account in accounts list in Settings showing that this user is managed by parent's account."> + Account managed by <ph name="PARENT_EMAIL">$1<ex>user@example.com</ex></ph>. To sign out of the primary account on this device, click the time on your screen. In the menu that appears, click "Sign out". + </message> + <message name="IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP" desc="Tooltip for the primary account in accounts list in Settings showing that this user is managed by two parents' accounts."> + Account managed by <ph name="FIRST_PARENT_EMAIL">$1<ex>first@example.com</ex></ph> and <ph name="SECOND_PARENT_EMAIL">$2<ex>second@example.com</ex></ph>. To sign out of the primary account on this device, click the time on your screen. In the menu that appears, click "Sign out". + </message> <message name="IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL" desc="Label of the Remove account button in Account Manager."> Remove this account </message> @@ -818,6 +824,9 @@ <message name="IDS_SETTINGS_PLUGIN_VM_CONFIRM_REMOVE_DIALOG_BODY" desc="Message of the confirmation dialog displayed before removal begins."> Removing Plugin VM will delete your VM. This includes its applications, settings, and data. Are you sure you wish to continue? </message> + <message name="IDS_SETTINGS_PLUGIN_VM_CAMERA_ACCESS_TITLE" desc="The text in the settings page for allowing camera access from Plugin VM."> + Give access to camera + </message> <!-- Crostini --> <message name="IDS_SETTINGS_CROSTINI_TITLE" desc="The title of Crostini section.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP.png.sha1 new file mode 100644 index 0000000..0d16bfc --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +76769a5956dd51706eaf82d94488d97ca5027069 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP.png.sha1 new file mode 100644 index 0000000..d3afd7a --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP.png.sha1
@@ -0,0 +1 @@ +e76198024821d9455a882a7d93b20a15e9014af3 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PLUGIN_VM_CAMERA_ACCESS_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PLUGIN_VM_CAMERA_ACCESS_TITLE.png.sha1 new file mode 100644 index 0000000..aef80c1c --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PLUGIN_VM_CAMERA_ACCESS_TITLE.png.sha1
@@ -0,0 +1 @@ +f94e7f724029c18d71fb54cddfdc0b93d9e246e0 \ No newline at end of file
diff --git a/chrome/browser/android/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc index 6e27427..51f4f0b 100644 --- a/chrome/browser/android/autofill_assistant/client_android.cc +++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -30,6 +30,7 @@ #include "components/autofill_assistant/browser/access_token_fetcher.h" #include "components/autofill_assistant/browser/controller.h" #include "components/autofill_assistant/browser/features.h" +#include "components/autofill_assistant/browser/switches.h" #include "components/autofill_assistant/browser/website_login_fetcher_impl.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" @@ -40,7 +41,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" -#include "google_apis/google_api_keys.h" #include "url/gurl.h" using base::android::AttachCurrentThread; @@ -48,16 +48,8 @@ using base::android::JavaRef; namespace autofill_assistant { -namespace switches { -const char* const kAutofillAssistantServerKey = "autofill-assistant-key"; -const char* const kAutofillAssistantUrl = "autofill-assistant-url"; -} // namespace switches - namespace { -const char* const kDefaultAutofillAssistantServerUrl = - "https://automate-pa.googleapis.com"; - // A direct action that corresponds to pressing the close or cancel button on // the UI. const char* const kCancelActionName = "cancel"; @@ -106,11 +98,6 @@ java_object_(Java_AutofillAssistantClient_create( AttachCurrentThread(), reinterpret_cast<intptr_t>(this))) { - server_url_ = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kAutofillAssistantUrl); - if (server_url_.empty()) { - server_url_ = kDefaultAutofillAssistantServerUrl; - } } ClientAndroid::~ClientAndroid() { @@ -449,19 +436,8 @@ ui_controller_android_.reset(); } -std::string ClientAndroid::GetApiKey() const { - std::string api_key; - if (google_apis::IsGoogleChromeAPIKeyUsed()) { - api_key = chrome::GetChannel() == version_info::Channel::STABLE - ? google_apis::GetAPIKey() - : google_apis::GetNonStableAPIKey(); - } - const auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kAutofillAssistantServerKey)) { - api_key = command_line->GetSwitchValueASCII( - switches::kAutofillAssistantServerKey); - } - return api_key; +version_info::Channel ClientAndroid::GetChannel() const { + return chrome::GetChannel(); } std::string ClientAndroid::GetAccountEmailAddress() const { @@ -504,10 +480,6 @@ return website_login_fetcher_.get(); } -std::string ClientAndroid::GetServerUrl() const { - return server_url_; -} - std::string ClientAndroid::GetLocale() const { return base::android::GetDefaultLocaleString(); } @@ -596,4 +568,4 @@ WEB_CONTENTS_USER_DATA_KEY_IMPL(ClientAndroid) -} // namespace autofill_assistant. +} // namespace autofill_assistant
diff --git a/chrome/browser/android/autofill_assistant/client_android.h b/chrome/browser/android/autofill_assistant/client_android.h index e23ec88..a85b835 100644 --- a/chrome/browser/android/autofill_assistant/client_android.h +++ b/chrome/browser/android/autofill_assistant/client_android.h
@@ -96,14 +96,13 @@ // Overrides Client void AttachUI() override; void DestroyUI() override; - std::string GetApiKey() const override; + version_info::Channel GetChannel() const override; std::string GetAccountEmailAddress() const override; AccessTokenFetcher* GetAccessTokenFetcher() override; autofill::PersonalDataManager* GetPersonalDataManager() const override; password_manager::PasswordManagerClient* GetPasswordManagerClient() const override; WebsiteLoginFetcher* GetWebsiteLoginFetcher() const override; - std::string GetServerUrl() const override; std::string GetLocale() const override; std::string GetCountryCode() const override; DeviceContext GetDeviceContext() const override; @@ -156,7 +155,6 @@ base::OnceCallback<void(bool, const std::string&)> fetch_access_token_callback_; - std::string server_url_; base::WeakPtrFactory<ClientAndroid> weak_ptr_factory_{this};
diff --git a/chrome/browser/apps/app_service/app_launch_params.cc b/chrome/browser/apps/app_service/app_launch_params.cc index 548409e..2bb4906 100644 --- a/chrome/browser/apps/app_service/app_launch_params.cc +++ b/chrome/browser/apps/app_service/app_launch_params.cc
@@ -22,31 +22,4 @@ AppLaunchParams::~AppLaunchParams() = default; -AppLaunchParams CreateAppIdLaunchParamsWithEventFlags( - const std::string& app_id, - int event_flags, - apps::mojom::AppLaunchSource source, - int64_t display_id, - apps::mojom::LaunchContainer fallback_container) { - WindowOpenDisposition raw_disposition = - ui::DispositionFromEventFlags(event_flags); - - apps::mojom::LaunchContainer container; - WindowOpenDisposition disposition; - if (raw_disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || - raw_disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { - container = apps::mojom::LaunchContainer::kLaunchContainerTab; - disposition = raw_disposition; - } else if (raw_disposition == WindowOpenDisposition::NEW_WINDOW) { - container = apps::mojom::LaunchContainer::kLaunchContainerWindow; - disposition = raw_disposition; - } else { - // Look at preference to find the right launch container. If no preference - // is set, launch as a regular tab. - container = fallback_container; - disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; - } - return AppLaunchParams(app_id, container, disposition, source, display_id); -} - } // namespace apps
diff --git a/chrome/browser/apps/app_service/app_launch_params.h b/chrome/browser/apps/app_service/app_launch_params.h index 3a7a3e9..db658e5 100644 --- a/chrome/browser/apps/app_service/app_launch_params.h +++ b/chrome/browser/apps/app_service/app_launch_params.h
@@ -74,16 +74,6 @@ std::vector<base::FilePath> launch_files; }; -// Helper to create AppLaunchParams using event flags that allows user to -// override the user-configured container using modifier keys. |display_id| is -// the id of the display from which the app is launched. -AppLaunchParams CreateAppIdLaunchParamsWithEventFlags( - const std::string& app_id, - int event_flags, - apps::mojom::AppLaunchSource source, - int64_t display_id, - apps::mojom::LaunchContainer fallback_container); - } // namespace apps #endif // CHROME_BROWSER_APPS_APP_SERVICE_APP_LAUNCH_PARAMS_H_
diff --git a/chrome/browser/apps/app_service/app_service_metrics.cc b/chrome/browser/apps/app_service/app_service_metrics.cc index 7cfc0273..1aef9004 100644 --- a/chrome/browser/apps/app_service/app_service_metrics.cc +++ b/chrome/browser/apps/app_service/app_service_metrics.cc
@@ -123,6 +123,10 @@ base::UmaHistogramEnumeration( "Apps.DefaultAppLaunch.FromInstalledNotification", default_app_name); break; + case apps::mojom::LaunchSource::kFromArc: + base::UmaHistogramEnumeration("Apps.DefaultAppLaunch.FromArc", + default_app_name); + break; } } @@ -153,6 +157,7 @@ case apps::mojom::LaunchSource::kFromMenu: case apps::mojom::LaunchSource::kFromInstalledNotification: case apps::mojom::LaunchSource::kFromTest: + case apps::mojom::LaunchSource::kFromArc: break; } }
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc index 61bdbba6..03d21188 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.cc +++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -244,11 +244,12 @@ void AppServiceProxy::LaunchAppWithIntent( const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) { if (app_service_.is_connected()) { - cache_.ForOneApp(app_id, [this, &intent, launch_source, + cache_.ForOneApp(app_id, [this, event_flags, &intent, launch_source, display_id](const apps::AppUpdate& update) { #if defined(OS_CHROMEOS) if (MaybeShowLaunchPreventionDialog(update)) { @@ -257,17 +258,18 @@ #endif RecordAppLaunch(update.AppId(), launch_source); app_service_->LaunchAppWithIntent(update.AppType(), update.AppId(), - std::move(intent), launch_source, - display_id); + event_flags, std::move(intent), + launch_source, display_id); }); } } void AppServiceProxy::LaunchAppWithUrl(const std::string& app_id, + int32_t event_flags, GURL url, apps::mojom::LaunchSource launch_source, int64_t display_id) { - LaunchAppWithIntent(app_id, apps_util::CreateIntentFromUrl(url), + LaunchAppWithIntent(app_id, event_flags, apps_util::CreateIntentFromUrl(url), launch_source, display_id); }
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h index b7fff63..ffa63499 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.h +++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -118,17 +118,23 @@ apps::mojom::FilePathsPtr file_paths); // Launches an app for the given |app_id|, passing |intent| to the app. + // |event_flags| provides additional context about the action which launch the + // app (e.g. a middle click indicating opening a background tab). // |launch_source| is the possible app launch sources. |display_id| is the id // of the display from which the app is launched. void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id); // Launches an app for the given |app_id|, passing |url| to the app. + // |event_flags| provides additional context about the action which launch the + // app (e.g. a middle click indicating opening a background tab). // |launch_source| is the possible app launch sources. |display_id| is the id // of the display from which the app is launched. void LaunchAppWithUrl(const std::string& app_id, + int32_t event_flags, GURL url, apps::mojom::LaunchSource launch_source, int64_t display_id);
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index eab8af6..7d789f74 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -515,6 +515,7 @@ } void ArcApps::LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) {
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h index f5a1ca64..95e15088 100644 --- a/chrome/browser/apps/app_service/arc_apps.h +++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -82,6 +82,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override;
diff --git a/chrome/browser/apps/app_service/browser_app_launcher.cc b/chrome/browser/apps/app_service/browser_app_launcher.cc index a340b35..c9886bf 100644 --- a/chrome/browser/apps/app_service/browser_app_launcher.cc +++ b/chrome/browser/apps/app_service/browser_app_launcher.cc
@@ -27,6 +27,23 @@ BrowserAppLauncher::~BrowserAppLauncher() = default; +content::WebContents* BrowserAppLauncher::LaunchAppWithParams( + const AppLaunchParams& params) { + const extensions::Extension* extension = + extensions::ExtensionRegistry::Get(profile_)->GetInstalledExtension( + params.app_id); + if ((!extension || extension->from_bookmark()) && web_app_launch_manager_) { + return web_app_launch_manager_->OpenApplication(params); + } + + if (params.container == + apps::mojom::LaunchContainer::kLaunchContainerWindow && + extension && extension->from_bookmark()) { + web_app::RecordAppWindowLaunch(profile_, params.app_id); + } + return ::OpenApplication(profile_, params); +} + void BrowserAppLauncher::LaunchAppWithCallback( const std::string& app_id, const base::CommandLine& command_line,
diff --git a/chrome/browser/apps/app_service/browser_app_launcher.h b/chrome/browser/apps/app_service/browser_app_launcher.h index dec1ec70..6d3caa92 100644 --- a/chrome/browser/apps/app_service/browser_app_launcher.h +++ b/chrome/browser/apps/app_service/browser_app_launcher.h
@@ -9,6 +9,7 @@ #include <string> #include "base/callback.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" #include "components/services/app_service/public/mojom/types.mojom.h" class Browser; @@ -19,6 +20,10 @@ class FilePath; } // namespace base +namespace content { +class WebContents; +} + namespace web_app { class WebAppLaunchManager; } // namespace web_app @@ -39,7 +44,10 @@ BrowserAppLauncher(const BrowserAppLauncher&) = delete; BrowserAppLauncher& operator=(const BrowserAppLauncher&) = delete; - // Attempt to open |app_id| in a new window or tab. Open an empty browser + // Launches an app for the given |app_id| in a way specified by |params|. + content::WebContents* LaunchAppWithParams(const AppLaunchParams& params); + + // Attempts to open |app_id| in a new window or tab. Open an empty browser // window if unsuccessful. The user's preferred launch container for the app // (standalone window or browser tab) is used. |callback| will be called with // the container type used to open the app, kLaunchContainerNone if an empty
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc index f4ade67..15a2949 100644 --- a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc +++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
@@ -189,6 +189,7 @@ void BuiltInChromeOsApps::LaunchAppWithIntent( const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) {
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.h b/chrome/browser/apps/app_service/built_in_chromeos_apps.h index 8ec8109..53b624e 100644 --- a/chrome/browser/apps/app_service/built_in_chromeos_apps.h +++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.h
@@ -52,6 +52,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override;
diff --git a/chrome/browser/apps/app_service/crostini_apps.cc b/chrome/browser/apps/app_service/crostini_apps.cc index d9c248a..da5f6e21 100644 --- a/chrome/browser/apps/app_service/crostini_apps.cc +++ b/chrome/browser/apps/app_service/crostini_apps.cc
@@ -179,6 +179,7 @@ } void CrostiniApps::LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) {
diff --git a/chrome/browser/apps/app_service/crostini_apps.h b/chrome/browser/apps/app_service/crostini_apps.h index d8059712..165eae04 100644 --- a/chrome/browser/apps/app_service/crostini_apps.h +++ b/chrome/browser/apps/app_service/crostini_apps.h
@@ -70,6 +70,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override;
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 85b0f69..fa18d30 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/arc/arc_web_contents_data.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limit_interface.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/extensions/gfx_utils.h" @@ -70,6 +71,7 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/clear_site_data_utils.h" +#include "content/public/browser/web_contents.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/management_policy.h" @@ -136,6 +138,7 @@ case apps::mojom::LaunchSource::kFromMenu: case apps::mojom::LaunchSource::kFromInstalledNotification: case apps::mojom::LaunchSource::kFromTest: + case apps::mojom::LaunchSource::kFromArc: return ash::LAUNCH_FROM_UNKNOWN; } } @@ -156,6 +159,22 @@ return launch_id; } +// Get the |apps::mojom::Readiness| for the |app_id|. If the extension is +// enabled, it returns |kReady|. If the extension is +// |DISABLE_BLOCKED_BY_POLICY|, it returns |kDisabledByPolicy|. Otherwise it +// returns |kDisabledByUser|. +apps::mojom::Readiness GetReadiness(const std::string& app_id, + extensions::ExtensionPrefs* prefs) { + DCHECK(prefs); + if (prefs->IsExtensionDisabled(app_id)) { + return prefs->HasDisableReason( + app_id, extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY) + ? apps::mojom::Readiness::kDisabledByPolicy + : apps::mojom::Readiness::kDisabledByUser; + } + return apps::mojom::Readiness::kReady; +} + } // namespace namespace apps { @@ -349,7 +368,9 @@ continue; } - Publish(Convert(extension, apps::mojom::Readiness::kReady)); + Publish(Convert( + extension, + GetReadiness(app_id, extensions::ExtensionPrefs::Get(profile_)))); } } @@ -364,7 +385,23 @@ extensions::ExtensionRegistry::Get(profile_); ConvertVector(registry->enabled_extensions(), apps::mojom::Readiness::kReady, &apps); - ConvertVector(registry->disabled_extensions(), + + extensions::ExtensionSet extensions_disabled_by_policy, + extensions_disabled_by_user; + const extensions::ExtensionPrefs* prefs = + extensions::ExtensionPrefs::Get(profile_); + for (const auto& extension : registry->disabled_extensions()) { + if (prefs->HasDisableReason( + extension->id(), + extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY)) { + extensions_disabled_by_policy.Insert(extension); + } else { + extensions_disabled_by_user.Insert(extension); + } + } + ConvertVector(extensions_disabled_by_policy, + apps::mojom::Readiness::kDisabledByPolicy, &apps); + ConvertVector(extensions_disabled_by_user, apps::mojom::Readiness::kDisabledByUser, &apps); ConvertVector(registry->terminated_extensions(), apps::mojom::Readiness::kTerminated, &apps); @@ -438,6 +475,7 @@ case apps::mojom::LaunchSource::kFromMenu: case apps::mojom::LaunchSource::kFromInstalledNotification: case apps::mojom::LaunchSource::kFromTest: + case apps::mojom::LaunchSource::kFromArc: break; } @@ -476,6 +514,7 @@ } void ExtensionApps::LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) { @@ -486,17 +525,30 @@ const extensions::Extension* extension = extensions::ExtensionRegistry::Get(profile_)->GetInstalledExtension( app_id); - if (!extension || !extensions::util::IsAppLaunchable(app_id, profile_) || - RunExtensionEnableFlow( - app_id, - base::BindOnce(&ExtensionApps::LaunchAppWithIntent, - weak_factory_.GetWeakPtr(), app_id, std::move(intent), - launch_source, display_id))) { + if (!extension || !extensions::util::IsAppLaunchable(app_id, profile_)) { return; } - AppLaunchParams params = CreateAppLaunchParamsForIntent(app_id, intent); - LaunchImpl(params); + if (!extensions::util::IsAppLaunchableWithoutEnabling(app_id, profile_)) { + RunExtensionEnableFlow( + app_id, base::BindOnce(&ExtensionApps::LaunchAppWithIntent, + weak_factory_.GetWeakPtr(), app_id, event_flags, + std::move(intent), launch_source, display_id)); + return; + } + + auto params = apps::CreateAppLaunchParamsForIntent( + app_id, event_flags, GetAppLaunchSource(launch_source), display_id, + extensions::GetLaunchContainer(extensions::ExtensionPrefs::Get(profile_), + extension), + intent); + auto* tab = LaunchImpl(params); + + if (launch_source == apps::mojom::LaunchSource::kFromArc && tab) { + // Add a flag to remember this tab originated in the ARC context. + tab->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag, + std::make_unique<arc::ArcWebContentsData>()); + } } void ExtensionApps::SetPermission(const std::string& app_id, @@ -935,7 +987,8 @@ switch (reason) { case extensions::UnloadedExtensionReason::DISABLE: - readiness = apps::mojom::Readiness::kDisabledByUser; + readiness = GetReadiness(extension->id(), + extensions::ExtensionPrefs::Get(profile_)); break; case extensions::UnloadedExtensionReason::BLACKLIST: readiness = apps::mojom::Readiness::kDisabledByBlacklist; @@ -1448,10 +1501,9 @@ std::move(callback).Run(std::move(menu_items)); } -void ExtensionApps::LaunchImpl(const AppLaunchParams& params) { +content::WebContents* ExtensionApps::LaunchImpl(const AppLaunchParams& params) { if (web_app_launch_manager_) { - web_app_launch_manager_->OpenApplication(params); - return; + return web_app_launch_manager_->OpenApplication(params); } if (params.container == @@ -1460,7 +1512,7 @@ web_app::RecordAppWindowLaunch(profile_, params.app_id); } - ::OpenApplication(profile_, params); + return ::OpenApplication(profile_, params); } } // namespace apps
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h index 3addc6d..7d2e720 100644 --- a/chrome/browser/apps/app_service/extension_apps.h +++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -36,6 +36,10 @@ class Profile; +namespace content { +class WebContents; +} + namespace extensions { class AppWindow; class ExtensionSet; @@ -100,6 +104,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override; @@ -215,7 +220,7 @@ void GetMenuModelForChromeBrowserApp(apps::mojom::MenuType menu_type, GetMenuModelCallback callback); - void LaunchImpl(const AppLaunchParams& params); + content::WebContents* LaunchImpl(const AppLaunchParams& params); mojo::Receiver<apps::mojom::Publisher> receiver_{this}; mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
diff --git a/chrome/browser/apps/app_service/launch_utils.cc b/chrome/browser/apps/app_service/launch_utils.cc index 7cfa5202..0220de4 100644 --- a/chrome/browser/apps/app_service/launch_utils.cc +++ b/chrome/browser/apps/app_service/launch_utils.cc
@@ -120,20 +120,53 @@ return browser; } +AppLaunchParams CreateAppIdLaunchParamsWithEventFlags( + const std::string& app_id, + int event_flags, + apps::mojom::AppLaunchSource source, + int64_t display_id, + apps::mojom::LaunchContainer fallback_container) { + WindowOpenDisposition raw_disposition = + ui::DispositionFromEventFlags(event_flags); + + apps::mojom::LaunchContainer container; + WindowOpenDisposition disposition; + if (raw_disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || + raw_disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { + container = apps::mojom::LaunchContainer::kLaunchContainerTab; + disposition = raw_disposition; + } else if (raw_disposition == WindowOpenDisposition::NEW_WINDOW) { + container = apps::mojom::LaunchContainer::kLaunchContainerWindow; + disposition = raw_disposition; + } else { + // Look at preference to find the right launch container. If no preference + // is set, launch as a regular tab. + container = fallback_container; + disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; + } + return AppLaunchParams(app_id, container, disposition, source, display_id); +} + apps::AppLaunchParams CreateAppLaunchParamsForIntent( const std::string& app_id, + int32_t event_flags, + apps::mojom::AppLaunchSource source, + int64_t display_id, + apps::mojom::LaunchContainer fallback_container, const apps::mojom::IntentPtr& intent) { - apps::AppLaunchParams params( - app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::NEW_FOREGROUND_TAB, - apps::mojom::AppLaunchSource::kSourceNone); + auto params = CreateAppIdLaunchParamsWithEventFlags( + app_id, event_flags, source, display_id, fallback_container); if (intent->scheme.has_value() && intent->host.has_value() && intent->path.has_value()) { params.source = apps::mojom::AppLaunchSource::kSourceIntentUrl; + std::string port; + if (intent->port.has_value()) { + port = ":" + intent->port.value(); + } params.override_url = GURL(intent->scheme.value() + url::kStandardSchemeSeparator + - intent->host.value() + intent->path.value()); + intent->host.value() + port + intent->path.value()); DCHECK(params.override_url.is_valid()); } @@ -166,6 +199,8 @@ return apps::mojom::AppLaunchSource::kSourceInstalledNotification; case apps::mojom::LaunchSource::kFromTest: return apps::mojom::AppLaunchSource::kSourceTest; + case apps::mojom::LaunchSource::kFromArc: + return apps::mojom::AppLaunchSource::kSourceArc; } }
diff --git a/chrome/browser/apps/app_service/launch_utils.h b/chrome/browser/apps/app_service/launch_utils.h index 37c4882..c502934b 100644 --- a/chrome/browser/apps/app_service/launch_utils.h +++ b/chrome/browser/apps/app_service/launch_utils.h
@@ -43,8 +43,22 @@ // the new tab page. Browser* CreateBrowserWithNewTabPage(Profile* profile); +// Helper to create AppLaunchParams using event flags that allows user to +// override the user-configured container using modifier keys. |display_id| is +// the id of the display from which the app is launched. +AppLaunchParams CreateAppIdLaunchParamsWithEventFlags( + const std::string& app_id, + int event_flags, + apps::mojom::AppLaunchSource source, + int64_t display_id, + apps::mojom::LaunchContainer fallback_container); + apps::AppLaunchParams CreateAppLaunchParamsForIntent( const std::string& app_id, + int32_t event_flags, + apps::mojom::AppLaunchSource source, + int64_t display_id, + apps::mojom::LaunchContainer fallback_container, const apps::mojom::IntentPtr& intent); apps::mojom::AppLaunchSource GetAppLaunchSource(
diff --git a/chrome/browser/apps/app_service/web_apps.cc b/chrome/browser/apps/app_service/web_apps.cc index a1e796b..10ded4e 100644 --- a/chrome/browser/apps/app_service/web_apps.cc +++ b/chrome/browser/apps/app_service/web_apps.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/arc/arc_web_contents_data.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/extensions/gfx_utils.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -54,6 +55,7 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/clear_site_data_utils.h" +#include "content/public/browser/web_contents.h" #include "url/url_constants.h" namespace { @@ -244,6 +246,7 @@ } void WebApps::LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) { @@ -251,8 +254,20 @@ return; } - AppLaunchParams params = CreateAppLaunchParamsForIntent(app_id, intent); - web_app_launch_manager_->OpenApplication(params); + auto params = apps::CreateAppLaunchParamsForIntent( + app_id, event_flags, GetAppLaunchSource(launch_source), display_id, + web_app::ConvertDisplayModeToAppLaunchContainer( + GetRegistrar().GetAppEffectiveDisplayMode(app_id)), + intent); + auto* tab = web_app_launch_manager_->OpenApplication(params); + + if (launch_source != apps::mojom::LaunchSource::kFromArc || !tab) { + return; + } + + // Add a flag to remember this tab originated in the ARC context. + tab->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag, + std::make_unique<arc::ArcWebContentsData>()); } void WebApps::SetPermission(const std::string& app_id,
diff --git a/chrome/browser/apps/app_service/web_apps.h b/chrome/browser/apps/app_service/web_apps.h index 922ddde..d3afc72 100644 --- a/chrome/browser/apps/app_service/web_apps.h +++ b/chrome/browser/apps/app_service/web_apps.h
@@ -82,6 +82,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override;
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc index b81d9d6a..86a801c0 100644 --- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc +++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/web_applications/components/app_shortcut_manager.h" #include "chrome/browser/web_applications/components/web_app_shortcut_mac.h" #include "chrome/browser/web_applications/web_app_provider.h" @@ -99,7 +101,9 @@ app_id, launch_container, WindowOpenDisposition::NEW_FOREGROUND_TAB, apps::mojom::AppLaunchSource::kSourceCommandLine); params.launch_files = files; - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); } void WebAppShimManagerDelegate::LaunchShim(
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc index 1bdfd2d..4354096b 100644 --- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc +++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc
@@ -19,7 +19,9 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/browser_process.h" @@ -274,7 +276,9 @@ WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest); params.command_line = *base::CommandLine::ForCurrentProcess(); - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); bool result = true; if (!catcher.GetNextResult()) {
diff --git a/chrome/browser/apps/platform_apps/app_browsertest.cc b/chrome/browser/apps/platform_apps/app_browsertest.cc index a262206..b6d47020 100644 --- a/chrome/browser/apps/platform_apps/app_browsertest.cc +++ b/chrome/browser/apps/platform_apps/app_browsertest.cc
@@ -20,7 +20,11 @@ #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" +#include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/devtools/devtools_window.h" @@ -64,6 +68,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "printing/buildflags/buildflags.h" #include "ui/base/window_open_disposition.h" +#include "ui/display/types/display_constants.h" #include "url/gurl.h" #if defined(OS_CHROMEOS) @@ -242,7 +247,9 @@ apps::mojom::AppLaunchSource::kSourceTest); params.command_line = command_line; params.current_directory = test_data_dir_; - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); if (!catcher.GetNextResult()) { message_ = catcher.message(); @@ -881,8 +888,9 @@ content::WindowedNotificationObserver app_loaded_observer( content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, content::NotificationService::AllSources()); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); @@ -1029,8 +1037,9 @@ ASSERT_TRUE(should_install.seen()); ExtensionTestMessageListener launched_listener("Launched", false); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); @@ -1053,8 +1062,9 @@ ASSERT_TRUE(extension); ExtensionTestMessageListener launched_listener("Launched", false); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); @@ -1093,8 +1103,9 @@ ASSERT_TRUE(should_install.seen()); ExtensionTestMessageListener launched_listener("Launched", false); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); @@ -1120,8 +1131,9 @@ { ExtensionTestMessageListener launched_listener("Launched", false); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); @@ -1242,12 +1254,14 @@ AppWindowRegistry* registry = AppWindowRegistry::Get(incognito_profile); ASSERT_TRUE(registry != NULL); registry->AddObserver(this); - - apps::LaunchService::Get(incognito_profile) - ->OpenApplication(CreateAppLaunchParamsUserContainer( - incognito_profile, file_manager, - WindowOpenDisposition::NEW_FOREGROUND_TAB, - apps::mojom::AppLaunchSource::kSourceTest)); + apps::AppServiceProxyFactory::GetForProfile(incognito_profile) + ->Launch(file_manager->id(), + apps::GetEventFlags( + apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_FOREGROUND_TAB, + true /* prefer_container */), + apps::mojom::LaunchSource::kFromTest, + display::kInvalidDisplayId); while (!base::Contains(opener_app_ids_, file_manager->id())) { content::RunAllPendingInMessageLoop();
diff --git a/chrome/browser/apps/platform_apps/app_browsertest_util.cc b/chrome/browser/apps/platform_apps/app_browsertest_util.cc index f7dc76ed..a64d9d82 100644 --- a/chrome/browser/apps/platform_apps/app_browsertest_util.cc +++ b/chrome/browser/apps/platform_apps/app_browsertest_util.cc
@@ -9,7 +9,10 @@ #include "base/command_line.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/api/tabs/tabs_api.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/ui/apps/chrome_app_delegate.h" @@ -154,16 +157,18 @@ } void PlatformAppBrowserTest::LaunchPlatformApp(const Extension* extension) { - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest)); } void PlatformAppBrowserTest::LaunchHostedApp(const Extension* extension) { - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(CreateAppLaunchParamsUserContainer( + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(CreateAppLaunchParamsUserContainer( browser()->profile(), extension, WindowOpenDisposition::NEW_FOREGROUND_TAB, apps::mojom::AppLaunchSource::kSourceCommandLine));
diff --git a/chrome/browser/apps/platform_apps/app_window_browsertest.cc b/chrome/browser/apps/platform_apps/app_window_browsertest.cc index 2337b18..bc73179 100644 --- a/chrome/browser/apps/platform_apps/app_window_browsertest.cc +++ b/chrome/browser/apps/platform_apps/app_window_browsertest.cc
@@ -5,7 +5,9 @@ #include "base/run_loop.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -231,8 +233,9 @@ test_data_dir_.AppendASCII("platform_apps").AppendASCII("window_api")); EXPECT_TRUE(extension); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc index ce39442..67beb29 100644 --- a/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc +++ b/chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.cc
@@ -5,8 +5,11 @@ #include "chrome/browser/apps/platform_apps/extension_app_shim_manager_delegate_mac.h" #include "apps/launcher.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/app_shim/app_shim_termination_manager.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/apps/platform_apps/app_window_registry_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/launch_util.h" @@ -180,7 +183,9 @@ profile, extension, WindowOpenDisposition::NEW_FOREGROUND_TAB, apps::mojom::AppLaunchSource::kSourceCommandLine); params.launch_files = files; - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); return; } if (files.empty()) {
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc index 4b1cbb5..4527e7a 100644 --- a/chrome/browser/background/background_mode_manager.cc +++ b/chrome/browser/background/background_mode_manager.cc
@@ -26,7 +26,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/background/background_application_list_model.h" #include "chrome/browser/background/background_mode_optimizer.h" #include "chrome/browser/browser_process.h" @@ -349,8 +351,9 @@ void BackgroundModeManager::LaunchBackgroundApplication( Profile* profile, const Extension* extension) { - apps::LaunchService::Get(profile)->OpenApplication( - CreateAppLaunchParamsUserContainer( + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(CreateAppLaunchParamsUserContainer( profile, extension, WindowOpenDisposition::NEW_FOREGROUND_TAB, apps::mojom::AppLaunchSource::kSourceBackground)); }
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc index 4ac093b..f1a0e257 100644 --- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc +++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -14,7 +14,9 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/app_mode/kiosk_diagnosis_runner.h" #include "chrome/browser/chromeos/app_mode/startup_app_launcher_update_checker.h" @@ -422,10 +424,12 @@ SYSLOG(INFO) << "Attempt to launch app."; // Always open the app in a window. - apps::LaunchService::Get(profile_)->OpenApplication(apps::AppLaunchParams( - extension->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceKiosk)); + apps::AppServiceProxyFactory::GetForProfile(profile_) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + apps::mojom::AppLaunchSource::kSourceKiosk)); KioskAppManager::Get()->InitSession(profile_, app_id_); session_manager::SessionManager::Get()->SessionStarted();
diff --git a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc index 876494f..183b829 100644 --- a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc +++ b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc
@@ -10,6 +10,7 @@ #include "base/stl_util.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" @@ -100,8 +101,12 @@ // TODO(crbug.com/853604): Distinguish the source from link and omnibox. apps::mojom::LaunchSource launch_source = apps::mojom::LaunchSource::kFromLink; - proxy->LaunchAppWithUrl(launch_name, url, launch_source, - display::kDefaultDisplayId); + proxy->LaunchAppWithUrl( + launch_name, + GetEventFlags(apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + /*prefer_container=*/true), + url, launch_source, display::kDefaultDisplayId); CloseOrGoBack(web_contents); } } @@ -211,8 +216,12 @@ if (preferred_app_id.has_value() && base::Contains(app_ids, preferred_app_id.value())) { auto launch_source = apps::mojom::LaunchSource::kFromLink; - proxy->LaunchAppWithUrl(preferred_app_id.value(), url, launch_source, - display::kDefaultDisplayId); + proxy->LaunchAppWithUrl( + preferred_app_id.value(), + GetEventFlags(apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + /*prefer_container=*/true), + url, launch_source, display::kDefaultDisplayId); CloseOrGoBack(web_contents); return true; }
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc index df9df0e..db1f5681 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h" +#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" #include "components/arc/mojom/accessibility_helper.mojom.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -15,9 +16,9 @@ using AXNodeInfoData = mojom::AccessibilityNodeInfoData; using AXStringProperty = mojom::AccessibilityStringProperty; -ax::mojom::Event ToAXEvent( - mojom::AccessibilityEventType arc_event_type, - mojom::AccessibilityNodeInfoData* focused_node_info_data) { +ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type, + AccessibilityInfoDataWrapper* source_node, + AccessibilityInfoDataWrapper* focused_node) { switch (arc_event_type) { case mojom::AccessibilityEventType::VIEW_FOCUSED: case mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: @@ -30,7 +31,7 @@ case mojom::AccessibilityEventType::VIEW_TEXT_SELECTION_CHANGED: return ax::mojom::Event::kTextSelectionChanged; case mojom::AccessibilityEventType::WINDOW_STATE_CHANGED: { - if (focused_node_info_data) + if (focused_node) return ax::mojom::Event::kFocus; else return ax::mojom::Event::kLayoutComplete; @@ -50,16 +51,14 @@ case mojom::AccessibilityEventType::VIEW_SCROLLED: return ax::mojom::Event::kScrollPositionChanged; case mojom::AccessibilityEventType::VIEW_SELECTED: { - // In Android, VIEW_SELECTED event is fired in the two cases below: - // 1. Changing a value in ProgressBar or TimePicker. - // (this usage is NOT documented) - // 2. Selecting an item in the context of an AdapterView. - // (officially documented in Android Developer doc below) - // https://developer.android.com/reference/android/view/accessibility/AccessibilityEvent#TYPE_VIEW_SELECTED - if (focused_node_info_data && focused_node_info_data->range_info) + // VIEW_SELECTED event is not selection event in Chrome. + // See the comment on AXTreeSourceArc::NotifyAccessibilityEvent. + if (source_node && source_node->IsNode() && + source_node->GetNode()->range_info) { return ax::mojom::Event::kValueChanged; - else - return ax::mojom::Event::kSelection; + } else { + return ax::mojom::Event::kFocus; + } } case mojom::AccessibilityEventType::VIEW_HOVER_EXIT: case mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_START:
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h index a3ef386..3c0d61f8 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h
@@ -14,9 +14,11 @@ #include "ui/accessibility/ax_enum_util.h" namespace arc { +class AccessibilityInfoDataWrapper; ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type, - mojom::AccessibilityNodeInfoData* node_info_data); + AccessibilityInfoDataWrapper* source_node, + AccessibilityInfoDataWrapper* focused_node); base::Optional<mojom::AccessibilityActionType> ConvertToAndroidAction( ax::mojom::Action action);
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index eafe90c..a76ebb97 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -24,6 +24,7 @@ using AXBooleanProperty = mojom::AccessibilityBooleanProperty; using AXEventData = mojom::AccessibilityEventData; +using AXEventIntProperty = mojom::AccessibilityEventIntProperty; using AXEventType = mojom::AccessibilityEventType; using AXIntProperty = mojom::AccessibilityIntProperty; using AXIntListProperty = mojom::AccessibilityIntListProperty; @@ -143,6 +144,26 @@ android_focused_id_ = IsValid(adjusted_node) ? adjusted_node->GetId() : event_data->source_id; } + } else if (event_data->event_type == AXEventType::VIEW_SELECTED) { + // In Android, VIEW_SELECTED event is dispatched in the two cases below: + // 1. Changing a value in ProgressBar or TimePicker. + // 2. Selecting an item in the context of an AdapterView. + AccessibilityInfoDataWrapper* source_node = + GetFromId(event_data->source_id); + if (!source_node || !source_node->IsNode()) + return; + AXNodeInfoData* node_info = source_node->GetNode(); + DCHECK(node_info); + + bool is_range_change = !node_info->range_info.is_null(); + if (!is_range_change) { + AccessibilityInfoDataWrapper* selected_node = + GetSelectedNodeInfoFromAdapterView(event_data); + if (!selected_node) + return; + + android_focused_id_ = selected_node->GetId(); + } } else if (event_data->event_type == AXEventType::WINDOW_STATE_CHANGED) { // When accessibility window changed, a11y event of WINDOW_CONTENT_CHANGED // is fired from Android multiple times. @@ -196,8 +217,8 @@ event_bundle.events.emplace_back(); ui::AXEvent& event = event_bundle.events.back(); - event.event_type = ToAXEvent( - event_data->event_type, focused_node ? focused_node->GetNode() : nullptr); + event.event_type = ToAXEvent(event_data->event_type, + GetFromId(event_data->source_id), focused_node); event.id = event_data->source_id; if (HasProperty(event_data->int_properties, @@ -452,6 +473,57 @@ return nullptr; } +AccessibilityInfoDataWrapper* +AXTreeSourceArc::GetSelectedNodeInfoFromAdapterView( + AXEventData* event_data) const { + AccessibilityInfoDataWrapper* source_node = GetFromId(event_data->source_id); + if (!source_node || !source_node->IsNode()) + return nullptr; + + AXNodeInfoData* node_info = source_node->GetNode(); + if (!node_info) + return nullptr; + + AccessibilityInfoDataWrapper* selected_node = source_node; + if (!node_info->collection_item_info) { + // The event source is not an item of AdapterView. If the event source is + // AdapterView, select the child. Otherwise, this is an unrelated event. + int item_count, from_index, current_item_index; + if (!GetProperty(event_data->int_properties, AXEventIntProperty::ITEM_COUNT, + &item_count) || + !GetProperty(event_data->int_properties, AXEventIntProperty::FROM_INDEX, + &from_index) || + !GetProperty(event_data->int_properties, + AXEventIntProperty::CURRENT_ITEM_INDEX, + ¤t_item_index)) { + return nullptr; + } + + int index = current_item_index - from_index; + if (index < 0) + return nullptr; + + std::vector<AccessibilityInfoDataWrapper*> children; + source_node->GetChildren(&children); + if (index >= static_cast<int>(children.size())) + return nullptr; + + selected_node = children[index]; + } + + // Sometimes a collection item is wrapped by a non-focusable node. + // Find a node with focusable property. + while (selected_node && !GetBooleanProperty(selected_node->GetNode(), + AXBooleanProperty::FOCUSABLE)) { + std::vector<AccessibilityInfoDataWrapper*> children; + selected_node->GetChildren(&children); + if (children.size() != 1) + break; + selected_node = children[0]; + } + return selected_node; +} + void AXTreeSourceArc::UpdateAXNameCache( AccessibilityInfoDataWrapper* focused_node, const std::vector<std::string>& event_text) {
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h index c11effa..6106e9f 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -126,6 +126,9 @@ AccessibilityInfoDataWrapper* FindFirstFocusableNode( AccessibilityInfoDataWrapper* info_data) const; + AccessibilityInfoDataWrapper* GetSelectedNodeInfoFromAdapterView( + mojom::AccessibilityEventData* event_data) const; + void UpdateAXNameCache(AccessibilityInfoDataWrapper* focused_node, const std::vector<std::string>& event_text);
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc index fdce147f..5ec25ff 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
@@ -22,6 +22,7 @@ using AXCollectionInfoData = mojom::AccessibilityCollectionInfoData; using AXCollectionItemInfoData = mojom::AccessibilityCollectionItemInfoData; using AXEventData = mojom::AccessibilityEventData; +using AXEventIntProperty = mojom::AccessibilityEventIntProperty; using AXEventType = mojom::AccessibilityEventType; using AXIntListProperty = mojom::AccessibilityIntListProperty; using AXIntProperty = mojom::AccessibilityIntProperty; @@ -98,6 +99,15 @@ prop_map.insert(std::make_pair(prop, value)); } +void SetProperty(AXEventData* event, AXEventIntProperty prop, int32_t value) { + if (!event->int_properties) { + event->int_properties = base::flat_map<AXEventIntProperty, int>(); + } + auto& prop_map = event->int_properties.value(); + base::EraseIf(prop_map, [prop](auto it) { return it.first == prop; }); + prop_map.insert(std::make_pair(prop, value)); +} + class MockAutomationEventRouter : public extensions::AutomationEventRouterInterface { public: @@ -965,6 +975,7 @@ TEST_F(AXTreeSourceArcTest, OnViewSelectedEvent) { auto event = AXEventData::New(); event->task_id = 1; + event->event_type = AXEventType::VIEW_SELECTED; event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); event->window_data->emplace_back(AXWindowInfoData::New()); @@ -973,32 +984,83 @@ root_window->root_node_id = 10; event->node_data.emplace_back(AXNodeInfoData::New()); - event->source_id = 1; // button->id AXNodeInfoData* root = event->node_data.back().get(); root->id = 10; SetProperty(root, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({1})); - // Add child node. event->node_data.emplace_back(AXNodeInfoData::New()); - AXNodeInfoData* button = event->node_data.back().get(); - button->id = 1; - SetProperty(button, AXBooleanProperty::FOCUSABLE, true); - SetProperty(button, AXBooleanProperty::IMPORTANCE, true); + AXNodeInfoData* list = event->node_data.back().get(); + list->id = 1; + SetProperty(list, AXBooleanProperty::FOCUSABLE, true); + SetProperty(list, AXBooleanProperty::IMPORTANCE, true); + SetProperty(list, AXIntListProperty::CHILD_NODE_IDS, + std::vector<int>({2, 3, 4})); - // Ensure that button has a focus. - event->event_type = AXEventType::VIEW_FOCUSED; - CallNotifyAccessibilityEvent(event.get()); + // Slider. + event->node_data.emplace_back(AXNodeInfoData::New()); + AXNodeInfoData* slider = event->node_data.back().get(); + slider->id = 2; + SetProperty(slider, AXBooleanProperty::FOCUSABLE, true); + SetProperty(slider, AXBooleanProperty::IMPORTANCE, true); + slider->range_info = AXRangeInfoData::New(); - // Without range_info, kSelection event should be emitted. Usually this event - // is fired from AdapterView. - event->event_type = AXEventType::VIEW_SELECTED; - CallNotifyAccessibilityEvent(event.get()); - EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kSelection)); + // Simple list item. + event->node_data.emplace_back(AXNodeInfoData::New()); + AXNodeInfoData* simple_item = event->node_data.back().get(); + simple_item->id = 3; + SetProperty(simple_item, AXBooleanProperty::FOCUSABLE, true); + SetProperty(simple_item, AXBooleanProperty::IMPORTANCE, true); + simple_item->collection_item_info = AXCollectionItemInfoData::New(); - // Set range_info, the event should be kValueChanged. - button->range_info = AXRangeInfoData::New(); + // This node is not focusable. + event->node_data.emplace_back(AXNodeInfoData::New()); + AXNodeInfoData* wrap_node = event->node_data.back().get(); + wrap_node->id = 4; + SetProperty(wrap_node, AXBooleanProperty::IMPORTANCE, true); + SetProperty(wrap_node, AXIntListProperty::CHILD_NODE_IDS, + std::vector<int>({5})); + wrap_node->collection_item_info = AXCollectionItemInfoData::New(); + + // A list item expected to get the focus. + event->node_data.emplace_back(AXNodeInfoData::New()); + AXNodeInfoData* item = event->node_data.back().get(); + item->id = 5; + SetProperty(item, AXBooleanProperty::FOCUSABLE, true); + SetProperty(item, AXBooleanProperty::IMPORTANCE, true); + + // A selected event from Slider is kValueChanged. + event->source_id = slider->id; CallNotifyAccessibilityEvent(event.get()); EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kValueChanged)); + + // A selected event from a collection. In Android, these event properties are + // populated by AdapterView. + event->source_id = list->id; + SetProperty(event.get(), AXEventIntProperty::ITEM_COUNT, 3); + SetProperty(event.get(), AXEventIntProperty::FROM_INDEX, 0); + SetProperty(event.get(), AXEventIntProperty::CURRENT_ITEM_INDEX, 2); + CallNotifyAccessibilityEvent(event.get()); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + ui::AXTreeData data; + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(item->id, data.focus_id); + + // A selected event from a collection item. + event->source_id = simple_item->id; + event->int_properties->clear(); + CallNotifyAccessibilityEvent(event.get()); + EXPECT_EQ(2, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(simple_item->id, data.focus_id); + + // A selected event from non collection node is dropped. + event->source_id = item->id; + event->int_properties->clear(); + CallNotifyAccessibilityEvent(event.get()); + EXPECT_EQ(2, + GetDispatchedEventCount(ax::mojom::Event::kFocus)); // not changed } TEST_F(AXTreeSourceArcTest, OnWindowStateChangedEvent) {
diff --git a/chrome/browser/chromeos/arc/arc_support_host.cc b/chrome/browser/chromeos/arc/arc_support_host.cc index 505e9c3..63a4d1bd 100644 --- a/chrome/browser/chromeos/arc/arc_support_host.cc +++ b/chrome/browser/chromeos/arc/arc_support_host.cc
@@ -15,7 +15,9 @@ #include "base/json/json_writer.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/consent_auditor/consent_auditor_factory.h" @@ -128,8 +130,9 @@ arc::kPlayStoreAppId); DCHECK(extension); DCHECK(extensions::util::IsAppLaunchable(arc::kPlayStoreAppId, profile)); - apps::LaunchService::Get(profile)->OpenApplication( - CreateAppLaunchParamsUserContainer( + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(CreateAppLaunchParamsUserContainer( profile, extension, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceChromeInternal)); }
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc index f6b696a..5be5f345c 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc
@@ -8,7 +8,9 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/extensions/component_loader.h" @@ -95,10 +97,12 @@ NetworkTypePattern::Physical(), false, chromeos::network_handler::ErrorCallback()); - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - extension_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceChromeInternal, true)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + apps::mojom::AppLaunchSource::kSourceChromeInternal, true)); KioskAppManager::Get()->InitSession(profile, extension_id); session_manager::SessionManager::Get()->SessionStarted();
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc index 430ff2a..667f1a6 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -24,7 +24,9 @@ #include "base/task/thread_pool.h" #include "base/timer/timer.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/platform_apps/app_load_service.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -567,10 +569,12 @@ return; Profile* profile = ProfileManager::GetActiveUserProfile(); DCHECK(profile); - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - extension->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceChromeInternal)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + apps::mojom::AppLaunchSource::kSourceChromeInternal)); } void DemoSession::OnAppWindowActivated(extensions::AppWindow* app_window) {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc index 06643eba..fa77339 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
@@ -13,6 +13,7 @@ #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time_to_iso8601.h" #include "base/timer/timer.h" #include "base/values.h" @@ -39,6 +40,7 @@ #include "chrome/browser/ui/webui/chromeos/login/network_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_update_engine_client.h" @@ -1169,6 +1171,87 @@ EXPECT_FALSE(IsCustomNetworkListElementShown("offlineDemoSetupListItemName")); } +class DemoSetupProgressStepsTest : public DemoSetupTestBase { + public: + DemoSetupProgressStepsTest() { + scoped_feature_list_.InitAndEnableFeature( + features::kShowStepsInDemoModeSetup); + } + ~DemoSetupProgressStepsTest() override = default; + + // Checks how many steps have been rendered in the demo setup screen. + int CountNumberOfStepsInUi() { + const std::string query = + "$('demo-setup-content').$$('oobe-dialog').querySelectorAll('progress-" + "list-item').length"; + + return test::OobeJS().GetInt(query); + } + + // Checks how many steps are marked as pending in the demo setup screen. + int CountPendingStepsInUi() { + const std::string query = + "Object.values($('demo-setup-content').$$('oobe-dialog')." + "querySelectorAll('progress-list-item')).filter(node => " + "node.shadowRoot.querySelector('#icon-pending:not([hidden])')).length"; + + return test::OobeJS().GetInt(query); + } + + // Checks how many steps are marked as active in the demo setup screen. + int CountActiveStepsInUi() { + const std::string query = + "Object.values($('demo-setup-content').$$('oobe-dialog')." + "querySelectorAll('progress-list-item')).filter(node => " + "node.shadowRoot.querySelector('#icon-active:not([hidden])')).length"; + + return test::OobeJS().GetInt(query); + } + + // Checks how many steps are marked as complete in the demo setup screen. + int CountCompletedStepsInUi() { + const std::string query = + "Object.values($('demo-setup-content').$$('oobe-dialog')." + "querySelectorAll('progress-list-item')).filter(node => " + "node.shadowRoot.querySelector('#icon-completed:not([hidden])'))." + "length"; + + return test::OobeJS().GetInt(query); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(DemoSetupProgressStepsTest); +}; + +IN_PROC_BROWSER_TEST_F(DemoSetupProgressStepsTest, + SetupProgessStepsDisplayCorrectly) { + auto* const wizard_controller = WizardController::default_controller(); + wizard_controller->SimulateDemoModeSetupForTesting( + DemoSession::DemoModeConfig::kOnline); + SimulateNetworkConnected(); + SkipToScreen(DemoSetupScreenView::kScreenId); + + DemoSetupScreen* demoSetupScreen = GetDemoSetupScreen(); + + DemoSetupController::DemoSetupStep orderedSteps[] = { + DemoSetupController::DemoSetupStep::kDownloadResources, + DemoSetupController::DemoSetupStep::kEnrollment, + DemoSetupController::DemoSetupStep::kComplete}; + + // Subtract 1 to account for kComplete step + int numSteps = + static_cast<int>(sizeof(orderedSteps) / sizeof(*orderedSteps)) - 1; + ASSERT_EQ(CountNumberOfStepsInUi(), numSteps); + + for (int i = 0; i < numSteps; i++) { + demoSetupScreen->SetCurrentSetupStepForTest(orderedSteps[i]); + ASSERT_EQ(CountPendingStepsInUi(), numSteps - i - 1); + ASSERT_EQ(CountActiveStepsInUi(), 1); + ASSERT_EQ(CountCompletedStepsInUi(), i); + } +} + class DemoSetupArcUnsupportedTest : public DemoSetupTestBase { public: DemoSetupArcUnsupportedTest() = default;
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc index 8d80d69..f21c75b 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
@@ -61,6 +61,19 @@ "DemoMode.Setup.LoadingDuration"; constexpr char kDemoSetupNumRetriesHistogram[] = "DemoMode.Setup.NumRetries"; +struct DemoSetupStepInfo { + DemoSetupController::DemoSetupStep step; + const int step_index; +}; + +base::span<const DemoSetupStepInfo> GetDemoSetupStepsInfo() { + static const DemoSetupStepInfo kDemoModeSetupStepsInfo[] = { + {DemoSetupController::DemoSetupStep::kDownloadResources, 0}, + {DemoSetupController::DemoSetupStep::kEnrollment, 1}, + {DemoSetupController::DemoSetupStep::kComplete, 2}}; + return kDemoModeSetupStepsInfo; +} + // Get the DeviceLocalAccountPolicyStore for the account_id. policy::CloudPolicyStore* GetDeviceLocalAccountPolicyStore( const std::string& account_id) { @@ -483,6 +496,32 @@ return std::string(); } +// static +base::Value DemoSetupController::GetDemoSetupSteps() { + base::Value setup_steps_dict(base::Value::Type::DICTIONARY); + for (auto entry : GetDemoSetupStepsInfo()) { + setup_steps_dict.SetIntPath(GetDemoSetupStepString(entry.step), + entry.step_index); + } + + return setup_steps_dict; +} + +// static +std::string DemoSetupController::GetDemoSetupStepString( + const DemoSetupStep step_enum) { + switch (step_enum) { + case DemoSetupStep::kDownloadResources: + return "downloadResources"; + case DemoSetupStep::kEnrollment: + return "enrollment"; + case DemoSetupStep::kComplete: + return "complete"; + } + + NOTREACHED(); +} + DemoSetupController::DemoSetupController() {} DemoSetupController::~DemoSetupController() { @@ -497,18 +536,20 @@ void DemoSetupController::Enroll( OnSetupSuccess on_setup_success, OnSetupError on_setup_error, - const OnIncrementSetupProgress& increment_setup_progress) { + const OnSetCurrentSetupStep& set_current_setup_step) { DCHECK_NE(demo_config_, DemoSession::DemoModeConfig::kNone) << "Demo config needs to be explicitly set before calling Enroll()"; DCHECK(!enrollment_helper_); - increment_setup_progress_ = increment_setup_progress; + set_current_setup_step_ = set_current_setup_step; on_setup_success_ = std::move(on_setup_success); on_setup_error_ = std::move(on_setup_error); VLOG(1) << "Starting demo setup " << DemoSession::DemoConfigToString(demo_config_); + SetCurrentSetupStep(DemoSetupStep::kDownloadResources); + switch (demo_config_) { case DemoSession::DemoModeConfig::kOnline: LoadDemoResourcesCrOSComponent(); @@ -577,7 +618,7 @@ base::TimeTicks::Now() - download_start_time_; base::UmaHistogramLongTimes100(kDemoSetupDownloadDurationHistogram, download_duration); - IncrementSetupProgress(/*complete=*/false); + SetCurrentSetupStep(DemoSetupStep::kEnrollment); if (demo_resources_->component_error().value() != component_updater::CrOSComponentManager::Error::NONE) { @@ -662,7 +703,6 @@ base::UmaHistogramLongTimes100(kDemoSetupEnrollDurationHistogram, enroll_duration); } - IncrementSetupProgress(/*complete=*/false); // Try to load the policy for the device local account. if (demo_config_ == DemoSession::DemoModeConfig::kOffline) { @@ -764,8 +804,6 @@ } void DemoSetupController::OnDeviceRegistered() { - IncrementSetupProgress(/*complete=*/true); - VLOG(1) << "Demo mode setup finished successfully."; if (demo_config_ == DemoSession::DemoModeConfig::kOnline) { @@ -782,6 +820,8 @@ base::UmaHistogramCounts100(kDemoSetupNumRetriesHistogram, num_setup_retries_); + SetCurrentSetupStep(DemoSetupStep::kComplete); + PrefService* prefs = g_browser_process->local_state(); prefs->SetInteger(prefs::kDemoModeConfig, static_cast<int>(demo_config_)); prefs->CommitPendingWrite(); @@ -790,9 +830,9 @@ std::move(on_setup_success_).Run(); } -void DemoSetupController::IncrementSetupProgress(bool complete) { - if (!increment_setup_progress_.is_null()) - increment_setup_progress_.Run(complete); +void DemoSetupController::SetCurrentSetupStep(DemoSetupStep current_step) { + if (!set_current_setup_step_.is_null()) + set_current_setup_step_.Run(current_step); } void DemoSetupController::SetupFailed(const DemoSetupError& error) {
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h index 4835332..aaf8322 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h
@@ -28,11 +28,21 @@ class DemoResources; -// Controlls enrollment flow for setting up Demo Mode. +// Controls enrollment flow for setting up Demo Mode. class DemoSetupController : public EnterpriseEnrollmentHelper::EnrollmentStatusConsumer, public policy::CloudPolicyStore::Observer { public: + // All steps required for setup. + enum class DemoSetupStep { + // Downloading Demo Mode resources. + kDownloadResources, + // Enrolling in Demo Mode. + kEnrollment, + // Setup is complete. + kComplete + }; + // Contains information related to setup error. class DemoSetupError { public: @@ -155,7 +165,8 @@ // Demo mode setup callbacks. using OnSetupSuccess = base::OnceClosure; using OnSetupError = base::OnceCallback<void(const DemoSetupError&)>; - using OnIncrementSetupProgress = base::RepeatingCallback<void(bool)>; + using OnSetCurrentSetupStep = + base::RepeatingCallback<void(const DemoSetupStep)>; using HasPreinstalledDemoResourcesCallback = base::OnceCallback<void(bool)>; static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); @@ -177,6 +188,12 @@ // Otherwise, returns an empty string. static std::string GetSubOrganizationEmail(); + // Returns a dictionary mapping setup steps to step indices. + static base::Value GetDemoSetupSteps(); + + // Converts a step enum to a string e.g. to sent to JavaScript. + static std::string GetDemoSetupStepString(const DemoSetupStep step_enum); + DemoSetupController(); ~DemoSetupController() override; @@ -194,11 +211,11 @@ // performed and it should be set with set_enrollment_type() before calling // Enroll(). |on_setup_success| will be called when enrollment finishes // successfully. |on_setup_error| will be called when enrollment finishes with - // an error. |update_setup_progress| will be called when enrollment progress - // is updated. + // an error. |set_current_setup_step| will be called when an enrollment step + // completes. void Enroll(OnSetupSuccess on_setup_success, OnSetupError on_setup_error, - const OnIncrementSetupProgress& increment_setup_progress); + const OnSetCurrentSetupStep& set_current_setup_step); // Tries to mount the preinstalled offline resources necessary for offline // Demo Mode. @@ -257,8 +274,8 @@ // is completed. This is the last step of demo mode setup flow. void OnDeviceRegistered(); - // Increments setup progress percentage for UI. - void IncrementSetupProgress(bool complete); + // Sets current setup step. + void SetCurrentSetupStep(DemoSetupStep current_step); // Finish the flow with an error. void SetupFailed(const DemoSetupError& error); @@ -292,8 +309,8 @@ // Path at which to mount preinstalled offline demo resources for tests. base::FilePath preinstalled_offline_resources_path_for_tests_; - // Callback to call when setup progress is updated. - OnIncrementSetupProgress increment_setup_progress_; + // Callback to call when setup step is updated. + OnSetCurrentSetupStep set_current_setup_step_; // Callback to call when enrollment finishes with an error. OnSetupError on_setup_error_;
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc index 8dc7eb55c..d5041f7 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller_unittest.cc
@@ -63,14 +63,24 @@ run_loop_->Quit(); } - void IncrementSetupProgress(const bool complete) {} + void SetCurrentSetupStep(DemoSetupController::DemoSetupStep current_step) { + setup_step_ = current_step; + } // Wait until the setup result arrives (either OnSetupError or OnSetupSuccess - // is called), returns true when the result matches with |expected|. - bool WaitResult(bool expected) { + // is called), returns true when the success result matches with + // |success_expected| and setup step matches |setup_step_expected|. + bool WaitResult(bool success_expected, + DemoSetupController::DemoSetupStep setup_step_expected) { // Run() stops immediately if Quit is already called. run_loop_->Run(); - return succeeded_.has_value() && succeeded_.value() == expected; + + const bool success_check = + succeeded_.has_value() && succeeded_.value() == success_expected; + const bool setup_step_check = + setup_step_.has_value() && setup_step_.value() == setup_step_expected; + + return success_check && setup_step_check; } // Returns true if powerwash is required to recover from the error. @@ -82,11 +92,13 @@ void Reset() { succeeded_.reset(); + setup_step_.reset(); run_loop_ = std::make_unique<base::RunLoop>(); } private: base::Optional<bool> succeeded_; + base::Optional<DemoSetupController::DemoSetupStep> setup_step_; base::Optional<DemoSetupController::DemoSetupError> error_; std::unique_ptr<base::RunLoop> run_loop_; @@ -162,11 +174,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(true)); + EXPECT_TRUE( + helper_->WaitResult(true, DemoSetupController::DemoSetupStep::kComplete)); EXPECT_EQ("", GetDeviceRequisition()); } @@ -190,11 +202,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kDownloadResources)); EXPECT_TRUE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -213,11 +225,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kDownloadResources)); EXPECT_TRUE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -241,11 +253,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kDownloadResources)); EXPECT_FALSE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -270,11 +282,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kDownloadResources)); EXPECT_TRUE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -288,11 +300,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(true)); + EXPECT_TRUE( + helper_->WaitResult(true, DemoSetupController::DemoSetupStep::kComplete)); EXPECT_EQ("", GetDeviceRequisition()); } @@ -305,11 +317,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kEnrollment)); EXPECT_FALSE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -324,11 +336,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kEnrollment)); EXPECT_TRUE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -346,11 +358,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kEnrollment)); EXPECT_FALSE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); } @@ -364,11 +376,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(false)); + EXPECT_TRUE(helper_->WaitResult( + false, DemoSetupController::DemoSetupStep::kEnrollment)); EXPECT_FALSE(helper_->RequiresPowerwash()); EXPECT_EQ("", GetDeviceRequisition()); @@ -382,11 +394,11 @@ base::Unretained(helper_.get())), base::BindOnce(&DemoSetupControllerTestHelper::OnSetupError, base::Unretained(helper_.get())), - base::BindRepeating( - &DemoSetupControllerTestHelper::IncrementSetupProgress, - base::Unretained(helper_.get()))); + base::BindRepeating(&DemoSetupControllerTestHelper::SetCurrentSetupStep, + base::Unretained(helper_.get()))); - EXPECT_TRUE(helper_->WaitResult(true)); + EXPECT_TRUE( + helper_->WaitResult(true, DemoSetupController::DemoSetupStep::kComplete)); EXPECT_EQ("", GetDeviceRequisition()); }
diff --git a/chrome/browser/chromeos/login/screens/demo_setup_screen.cc b/chrome/browser/chromeos/login/screens/demo_setup_screen.cc index f865c8baf..d21e6438 100644 --- a/chrome/browser/chromeos/login/screens/demo_setup_screen.cc +++ b/chrome/browser/chromeos/login/screens/demo_setup_screen.cc
@@ -76,12 +76,18 @@ weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&DemoSetupScreen::OnSetupError, weak_ptr_factory_.GetWeakPtr()), - base::BindRepeating(&DemoSetupScreen::IncrementSetupProgress, + base::BindRepeating(&DemoSetupScreen::SetCurrentSetupStep, weak_ptr_factory_.GetWeakPtr())); } -void DemoSetupScreen::IncrementSetupProgress(bool complete) { - view_->IncrementSetupProgress(complete); +void DemoSetupScreen::SetCurrentSetupStep( + const DemoSetupController::DemoSetupStep current_step) { + view_->SetCurrentSetupStep(current_step); +} + +void DemoSetupScreen::SetCurrentSetupStepForTest( + const DemoSetupController::DemoSetupStep current_step) { + SetCurrentSetupStep(current_step); } void DemoSetupScreen::OnSetupError(
diff --git a/chrome/browser/chromeos/login/screens/demo_setup_screen.h b/chrome/browser/chromeos/login/screens/demo_setup_screen.h index 1327c97..d924967 100644 --- a/chrome/browser/chromeos/login/screens/demo_setup_screen.h +++ b/chrome/browser/chromeos/login/screens/demo_setup_screen.h
@@ -17,7 +17,7 @@ class DemoSetupScreenView; -// Controlls demo mode setup. The screen can be shown during OOBE. It allows +// Controls demo mode setup. The screen can be shown during OOBE. It allows // user to setup retail demo mode on the device. class DemoSetupScreen : public BaseScreen { public: @@ -34,6 +34,10 @@ // then it has to call Bind(nullptr). void OnViewDestroyed(DemoSetupScreenView* view); + // Test utilities. + void SetCurrentSetupStepForTest( + const DemoSetupController::DemoSetupStep current_step); + protected: // BaseScreen: void ShowImpl() override; @@ -45,8 +49,9 @@ private: void StartEnrollment(); - // Increments setup progress percentage for UI. - void IncrementSetupProgress(bool complete); + // Updates current setup step. + void SetCurrentSetupStep( + const DemoSetupController::DemoSetupStep current_step); // Called when the setup flow finished with error. void OnSetupError(const DemoSetupController::DemoSetupError& error);
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc index e8f0bf1..bbbcb42 100644 --- a/chrome/browser/chromeos/login/screens/error_screen.cc +++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -11,7 +11,9 @@ #include "base/logging.h" #include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/certificate_manager_dialog.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" @@ -299,10 +301,12 @@ IDR_CONNECTIVITY_DIAGNOSTICS_MANIFEST, base::FilePath(extension_misc::kConnectivityDiagnosticsPath)); - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - extension_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceChromeInternal)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, + apps::mojom::AppLaunchSource::kSourceChromeInternal)); KioskAppManager::Get()->InitSession(profile, extension_id); LoginDisplayHost::default_host()->Finalize(base::BindOnce(
diff --git a/chrome/browser/chromeos/login/screens/mock_demo_setup_screen.h b/chrome/browser/chromeos/login/screens/mock_demo_setup_screen.h index 4b143a9..94c22eaf 100644 --- a/chrome/browser/chromeos/login/screens/mock_demo_setup_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_demo_setup_screen.h
@@ -35,7 +35,8 @@ MOCK_METHOD0(OnSetupSucceeded, void()); MOCK_METHOD1(OnSetupFailed, void(const DemoSetupController::DemoSetupError& error)); - MOCK_METHOD1(IncrementSetupProgress, void(bool complete)); + MOCK_METHOD1(SetCurrentSetupStep, + void(const DemoSetupController::DemoSetupStep current_step)); void Bind(DemoSetupScreen* screen) override;
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc index 16c5493..0cea588 100644 --- a/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/ui/user_adding_screen_browsertest.cc
@@ -167,7 +167,8 @@ } // TODO(crbug.com/1067461): Flakes on ASAN and linux-chromeos-dbg -#if defined(OS_CHROMEOS) && (defined(ADDRESS_SANITIZER) || !defined(NDEBUG)) +#if defined(OS_CHROMEOS) && (defined(ADDRESS_SANITIZER) || \ + defined(MEMORY_SANITIZER) || !defined(NDEBUG)) #define MAYBE_AddingSeveralUsers DISABLED_AddingSeveralUsers #else #define MAYBE_AddingSeveralUsers AddingSeveralUsers
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.cc index 65821434..b38890b1 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.cc
@@ -23,6 +23,9 @@ const char kPluginVmImageExists[] = "plugin_vm.image_exists"; // A boolean preference indicating whether Plugin VM is allowed to use printers. const char kPluginVmPrintersAllowed[] = "plugin_vm.printers_allowed"; +// A boolean preference indicating whether the camera should be shared with +// PluginVm. +const char kPluginVmCameraSharing[] = "plugin_vm.camera_sharing"; // Preferences for storing engagement time data, as per // GuestOsEngagementMetrics. const char kEngagementPrefsPrefix[] = "plugin_vm.metrics"; @@ -33,6 +36,7 @@ // TODO(crbug.com/1066760): For convenience this currently defaults to true, // but we'll need to revisit before launch. registry->RegisterBooleanPref(kPluginVmPrintersAllowed, true); + registry->RegisterBooleanPref(kPluginVmCameraSharing, false); guest_os::prefs::RegisterEngagementProfilePrefs(registry, kEngagementPrefsPrefix);
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h index 1f26dc6..bb54660 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h
@@ -13,6 +13,7 @@ extern const char kPluginVmImage[]; extern const char kPluginVmImageExists[]; extern const char kPluginVmPrintersAllowed[]; +extern const char kPluginVmCameraSharing[]; extern const char kEngagementPrefsPrefix[]; void RegisterProfilePrefs(PrefRegistrySimple* registry);
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h index e032ee0..1db457e 100644 --- a/chrome/browser/devtools/devtools_eye_dropper.h +++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -51,6 +51,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) override; void OnStopped() override; + void OnLog(const std::string& /*message*/) override {} EyeDropperCallback callback_; SkBitmap frame_;
diff --git a/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc b/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc index 83041ce..364dcd5 100644 --- a/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc +++ b/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" +#include "chrome/common/channel_info.h" #include "components/autofill/core/browser/field_types.h" #include "extensions/browser/event_router_factory.h" @@ -314,10 +315,11 @@ void AutofillAssistantPrivateAPI::DestroyUI() {} -std::string AutofillAssistantPrivateAPI::GetApiKey() const { - // TODO(crbug.com/1015753): Use chromium's keys and also consider the - // autofill-assistant-key here to override that particular key. - return "invalid"; +version_info::Channel AutofillAssistantPrivateAPI::GetChannel() const { + // TODO(crbug.com/1015753): Make a minimal client impl available in a common + // chrome/browser/autofill_assistant and share it with the android client + // impl. + return chrome::GetChannel(); } std::string AutofillAssistantPrivateAPI::GetAccountEmailAddress() const { @@ -346,13 +348,6 @@ return nullptr; } -std::string AutofillAssistantPrivateAPI::GetServerUrl() const { - // TODO(crbug.com/1015753): Consider the autofill-assistant-url for endpoint - // overrides and share the kDefaultAutofillAssistantServerUrl to expose it - // here. - return "https://automate-pa.googleapis.com"; -} - std::string AutofillAssistantPrivateAPI::GetLocale() const { return "en-us"; }
diff --git a/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h b/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h index d047699d..796cf65 100644 --- a/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h +++ b/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h
@@ -196,7 +196,7 @@ // autofill_assistant::Client: void AttachUI() override; void DestroyUI() override; - std::string GetApiKey() const override; + version_info::Channel GetChannel() const override; std::string GetAccountEmailAddress() const override; autofill_assistant::AccessTokenFetcher* GetAccessTokenFetcher() override; autofill::PersonalDataManager* GetPersonalDataManager() const override; @@ -204,7 +204,6 @@ const override; autofill_assistant::WebsiteLoginFetcher* GetWebsiteLoginFetcher() const override; - std::string GetServerUrl() const override; std::string GetLocale() const override; std::string GetCountryCode() const override; autofill_assistant::DeviceContext GetDeviceContext() const override;
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc index 5d08050..0a2c027 100644 --- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc +++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -13,7 +13,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/launch_util.h" @@ -327,9 +329,11 @@ if (display_mode == blink::mojom::DisplayMode::kBrowser) launch_container = apps::mojom::LaunchContainer::kLaunchContainerTab; - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - app_id, launch_container, WindowOpenDisposition::NEW_FOREGROUND_TAB, - apps::mojom::AppLaunchSource::kSourceManagementApi)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + app_id, launch_container, WindowOpenDisposition::NEW_FOREGROUND_TAB, + apps::mojom::AppLaunchSource::kSourceManagementApi)); } void OnWebAppInstallCompleted(InstallOrLaunchWebAppCallback callback, @@ -389,10 +393,12 @@ extensions::LaunchContainer launch_container = GetLaunchContainer(extensions::ExtensionPrefs::Get(context), extension); Profile* profile = Profile::FromBrowserContext(context); - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - extension->id(), launch_container, - WindowOpenDisposition::NEW_FOREGROUND_TAB, - apps::mojom::AppLaunchSource::kSourceManagementApi)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension->id(), launch_container, + WindowOpenDisposition::NEW_FOREGROUND_TAB, + apps::mojom::AppLaunchSource::kSourceManagementApi)); #if defined(OS_CHROMEOS) chromeos::DemoSession::RecordAppLaunchSourceIfInDemoMode( @@ -592,7 +598,7 @@ // for, and received parent permission to install the extension. SupervisedUserService* supervised_user_service = SupervisedUserServiceFactory::GetForBrowserContext(context); - supervised_user_service->AddExtensionApproval(*extension); + supervised_user_service->AddOrUpdateExtensionApproval(*extension); #endif // If the extension was disabled for a permissions increase, the Management
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc index 3c64e1f..799c3c57 100644 --- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc +++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -11,7 +11,9 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/extensions/api/notifications/extension_notification_display_helper.h" #include "chrome/browser/extensions/api/notifications/extension_notification_display_helper_factory.h" @@ -205,8 +207,9 @@ } void LaunchPlatformApp(const Extension* extension) { - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 99993cc..01a1b46 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -473,6 +473,8 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[plugin_vm::prefs::kPluginVmPrintersAllowed] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[plugin_vm::prefs::kPluginVmCameraSharing] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; // Android Apps. (*s_whitelist)[arc::prefs::kArcEnabled] =
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index 92a6382..99b1e505 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -509,7 +509,7 @@ OnParentPermissionReceived() { SupervisedUserService* service = SupervisedUserServiceFactory::GetForProfile(chrome_details_.GetProfile()); - service->AddExtensionApproval(*dummy_extension_); + service->AddOrUpdateExtensionApproval(*dummy_extension_); HandleInstallProceed(); Release(); // Matches the AddRef in Run().
diff --git a/chrome/browser/extensions/browsertest_util.cc b/chrome/browser/extensions/browsertest_util.cc index d03fba0..b5b86ac4 100644 --- a/chrome/browser/extensions/browsertest_util.cc +++ b/chrome/browser/extensions/browsertest_util.cc
@@ -12,7 +12,9 @@ #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/profiles/profile.h" @@ -91,9 +93,12 @@ Browser* LaunchAppBrowser(Profile* profile, const Extension* extension_app) { EXPECT_TRUE( - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - extension_app->id(), LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::CURRENT_TAB, AppLaunchSource::kSourceTest))); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension_app->id(), LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::CURRENT_TAB, + AppLaunchSource::kSourceTest))); Browser* browser = chrome::FindLastActive(); bool is_correct_app_browser =
diff --git a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc index f6974cd..69f1f4c3 100644 --- a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc +++ b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
@@ -13,7 +13,9 @@ #include "base/test/metrics/histogram_tester.h" #include "base/values.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/api/tabs/tabs_api.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_function_test_utils.h" @@ -1693,8 +1695,9 @@ content::WebContents* app_contents = nullptr; { content::WebContentsAddedObserver new_contents_observer; - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( app->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index ef53294..b971613 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc
@@ -17,7 +17,9 @@ #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/profiles/profile.h" @@ -298,7 +300,9 @@ extension->id(), LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, AppLaunchSource::kSourceTest); params.command_line = *base::CommandLine::ForCurrentProcess(); - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); } if (!catcher.GetNextResult()) {
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index cde9909..723185b 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -24,7 +24,9 @@ #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/browsertest_util.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/component_loader.h" @@ -436,7 +438,9 @@ WindowOpenDisposition::NEW_WINDOW, AppLaunchSource::kSourceTest); params.command_line = *base::CommandLine::ForCurrentProcess(); - apps::LaunchService::Get(profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); app_loaded_observer.Wait(); return app;
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc index 15c0eb0..d252c0f7 100644 --- a/chrome/browser/extensions/extension_service_sync_unittest.cc +++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -1925,16 +1925,6 @@ EXPECT_EQ(base::Version(version), extension->version()); } - // Simulate a custodian or child approval for enabling the extension coming in - // through Sync by adding the approved version to the map of approved - // extensions. It doesn't simulate a change in the disable reasons. - void SimulateApprovalChangeViaSync(const std::string& extension_id, - const std::string& version, - SyncChange::SyncChangeType type) { - supervised_user_service()->UpdateApprovedExtensions(extension_id, version, - type); - } - void CheckDisabledForCustodianApproval(const std::string& extension_id) { EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id)); ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile()); @@ -2053,13 +2043,12 @@ base::FilePath path = data_dir().AppendASCII("good.crx"); const Extension* extension = InstallCRX(path, INSTALL_NEW); std::string id = extension->id(); - const std::string version("1.0.0.0"); // The extension should be enabled. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); // Simulate custodian approval. - SimulateApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD); + supervised_user_service()->AddOrUpdateExtensionApproval(*extension); // The extension should still be enabled. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); } @@ -2154,7 +2143,8 @@ std::string id = good_crx; std::string version("1.0.0.0"); - SimulateApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version, SupervisedUserService::ApprovedExtensionChange::kNew); // Now install an extension. base::FilePath path = data_dir().AppendASCII("good.crx"); @@ -2179,7 +2169,8 @@ // Save the id, as the extension object will be destroyed during updating. std::string id = InstallNoPermissionsTestExtension(); std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // Update to a new version. std::string version2("2"); @@ -2215,7 +2206,8 @@ // Simulate a custodian approval for re-enabling the extension coming in // through Sync, but set the old version. This can happen when there already // was a pending request for an earlier version of the extension. - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // The re-enable should be ignored, since the version doesn't match. EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); @@ -2245,7 +2237,8 @@ // Simulate a custodian approval for re-enabling the extension coming in // through Sync. - SimulateApprovalChangeViaSync(id, version2, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version2, SupervisedUserService::ApprovedExtensionChange::kNew); // The extension should have gotten re-enabled. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2280,7 +2273,8 @@ std::string id = InstallPermissionsTestExtension(); const std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // Should see 1 kNewExtensionApprovalGranted metric count recorded. histogram_tester.ExpectUniqueSample( @@ -2301,7 +2295,8 @@ // Simulate a custodian approval for re-enabling the extension coming in // through Sync. Set a newer version than we have installed. const std::string version3("3"); - SimulateApprovalChangeViaSync(id, version3, SyncChange::ACTION_UPDATE); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version3, SupervisedUserService::ApprovedExtensionChange::kUpdate); // The re-enable should be delayed until the extension is updated to the // matching version. @@ -2352,7 +2347,6 @@ SetSupervisedUserExtensionsMayRequestPermissionsPref(true)); base::FilePath path = data_dir().AppendASCII("good.crx"); - std::string version("1.0.0.0"); // Should be installed but disabled. const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD); @@ -2361,14 +2355,14 @@ EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx)); EXPECT_TRUE(IsPendingCustodianApproval(extension->id())); - SimulateApprovalChangeViaSync(good_crx, version, SyncChange::ACTION_ADD); + supervised_user_service()->AddOrUpdateExtensionApproval(*extension); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx)); EXPECT_FALSE(IsPendingCustodianApproval(extension->id())); // Simulate approval removal coming via Sync. - SimulateApprovalChangeViaSync(good_crx, version, SyncChange::ACTION_DELETE); + supervised_user_service()->RemoveExtensionApproval(*extension); // The extension should be disabled now. EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx)); @@ -2388,7 +2382,8 @@ std::string id = InstallNoPermissionsTestExtension(); std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2407,14 +2402,14 @@ // Check that the approved version has been updated in the prefs as well. // Prefs are updated via Sync. If the prefs are updated, then the new // approved version has been pushed to Sync as well. - std::string approved_version; - std::string key = SupervisedUserSettingsService::MakeSplitSettingKey( - supervised_users::kApprovedExtensions, id); + PrefService* pref_service = profile()->GetPrefs(); + ASSERT_TRUE(pref_service); const base::DictionaryValue* approved_extensions = - supervised_user_settings_service()->GetDictionaryAndSplitKey(&key); - approved_extensions->GetStringWithoutPathExpansion(id, &approved_version); + pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions); + const std::string* approved_version = approved_extensions->FindStringKey(id); + ASSERT_TRUE(approved_version); - EXPECT_EQ(base::Version(approved_version), extension->version()); + EXPECT_EQ(base::Version(*approved_version), extension->version()); EXPECT_FALSE(IsPendingCustodianApproval(id)); } @@ -2431,7 +2426,8 @@ std::string id = InstallPermissionsTestExtension(); std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2447,7 +2443,8 @@ std::string version2("2"); // Approve an older version - SimulateApprovalChangeViaSync(id, version2, SyncChange::ACTION_UPDATE); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version2, SupervisedUserService::ApprovedExtensionChange::kUpdate); // The extension should remain disabled. EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); @@ -2458,7 +2455,8 @@ EXPECT_TRUE(IsPendingCustodianApproval(id)); // Approve the latest version - SimulateApprovalChangeViaSync(id, version3, SyncChange::ACTION_UPDATE); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version3, SupervisedUserService::ApprovedExtensionChange::kUpdate); // The extension should be enabled again. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2478,14 +2476,16 @@ std::string id = InstallPermissionsTestExtension(); std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); std::string version2("2"); // Approve a newer version - SimulateApprovalChangeViaSync(id, version2, SyncChange::ACTION_UPDATE); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version2, SupervisedUserService::ApprovedExtensionChange::kUpdate); // The extension should be disabled. CheckDisabledForCustodianApproval(id); @@ -2554,7 +2554,8 @@ // Now approve the extension. const std::string version1("1"); - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + supervised_user_service()->UpdateApprovedExtensionForTesting( + id, version1, SupervisedUserService::ApprovedExtensionChange::kNew); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2593,6 +2594,8 @@ InitSupervisedUserExtensionInstallFeatures( SupervisedUserExtensionInstallFeatureMode::kFull); + base::HistogramTester histogram_tester; + InitServices(/*profile_is_supervised=*/true); SetSupervisedUserExtensionsMayRequestPermissionsPref(true); @@ -2600,7 +2603,17 @@ std::string id = InstallPermissionsTestExtension(); const std::string version1("1"); // Simulate parent granting approval for the initial version. - SimulateApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD); + const Extension* extension1 = registry()->disabled_extensions().GetByID(id); + ASSERT_TRUE(extension1); + supervised_user_service()->AddOrUpdateExtensionApproval(*extension1); + + // Should see 1 kNewExtensionApprovalGranted metric count recorded. + histogram_tester.ExpectUniqueSample( + "SupervisedUsers.Extensions", + SupervisedUserExtensionsMetricsRecorder::UmaExtensionState:: + kNewExtensionApprovalGranted, + 1); + histogram_tester.ExpectTotalCount("SupervisedUsers.Extensions", 1); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2611,8 +2624,18 @@ UpdatePermissionsTestExtension(id, version2, DISABLED); EXPECT_TRUE(IsPendingCustodianApproval(id)); + const Extension* extension2 = registry()->disabled_extensions().GetByID(id); + ASSERT_TRUE(extension2); // Simulate child granting approval for the new permissions. - SimulateApprovalChangeViaSync(id, version2, SyncChange::ACTION_UPDATE); + supervised_user_service()->AddOrUpdateExtensionApproval(*extension2); + + // Should see 1 kNewVersionApprovalGranted metric count recorded. + histogram_tester.ExpectBucketCount( + "SupervisedUsers.Extensions", + SupervisedUserExtensionsMetricsRecorder::UmaExtensionState:: + kNewVersionApprovalGranted, + 1); + histogram_tester.ExpectTotalCount("SupervisedUsers.Extensions", 2); // The extension should be enabled now. EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); @@ -2628,7 +2651,17 @@ // The child should not be able to approve additional permissions when // kSupervisedUserExtensionsMayRequestPermissions is false, but suppose // somehow the child is able to circumvent controls and grant approval. - SimulateApprovalChangeViaSync(id, version3, SyncChange::ACTION_UPDATE); + const Extension* extension3 = registry()->disabled_extensions().GetByID(id); + ASSERT_TRUE(extension3); + supervised_user_service()->AddOrUpdateExtensionApproval(*extension3); + + // Should see 1 kNewVersionApprovalGranted metric count recorded. + histogram_tester.ExpectBucketCount( + "SupervisedUsers.Extensions", + SupervisedUserExtensionsMetricsRecorder::UmaExtensionState:: + kNewVersionApprovalGranted, + 2); + histogram_tester.ExpectTotalCount("SupervisedUsers.Extensions", 3); // The extension should still be blocked. EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
diff --git a/chrome/browser/extensions/standard_management_policy_provider.cc b/chrome/browser/extensions/standard_management_policy_provider.cc index 46ca4e6..785ee71 100644 --- a/chrome/browser/extensions/standard_management_policy_provider.cc +++ b/chrome/browser/extensions/standard_management_policy_provider.cc
@@ -85,19 +85,26 @@ bool StandardManagementPolicyProvider::UserMayLoad( const Extension* extension, base::string16* error) const { + ExtensionManagement::InstallationMode installation_mode = + settings_->GetInstallationMode(extension); + + // TODO(crbug.com/1065865): The special check for kOsSettingsAppId should be + // removed once OSSettings is moved to WebApps. +#if defined(OS_CHROMEOS) + if (extension->id() == chromeos::default_web_apps::kOsSettingsAppId && + (installation_mode == ExtensionManagement::INSTALLATION_BLOCKED || + installation_mode == ExtensionManagement::INSTALLATION_REMOVED)) { + return ReturnLoadError(extension, error); + } +#endif // defined(OS_CHROMEOS) + // Component extensions are always allowed, besides the camera app that can be // disabled by extension policy. This is a temporary solution until there's a // dedicated policy to disable the camera, at which point the special check in // the 'if' statement should be removed. // TODO(http://crbug.com/1002935) - // TODO(crbug.com/1065865): The special check for kOsSettingsAppId should be - // removed once OSSettings is moved to WebApps. if (Manifest::IsComponentLocation(extension->location()) && - extension->id() != extension_misc::kCameraAppId -#if defined(OS_CHROMEOS) - && extension->id() != chromeos::default_web_apps::kOsSettingsAppId -#endif // defined(OS_CHROMEOS) - ) { + extension->id() != extension_misc::kCameraAppId) { return true; } @@ -112,13 +119,7 @@ // by extension management policies. See crbug.com/786061. // TODO(calamity): This special case should be removed by removing bookmark // apps from external sources. See crbug.com/788245. - // TODO(crbug.com/1065865): The special check for kOsSettingsAppId should be - // removed once OSSettings is moved to WebApps. - if (extension->from_bookmark() -#if defined(OS_CHROMEOS) - && extension->id() != chromeos::default_web_apps::kOsSettingsAppId -#endif // defined(OS_CHROMEOS) - ) + if (extension->from_bookmark()) return true; // Check whether the extension type is allowed. @@ -148,8 +149,6 @@ NOTREACHED(); } - ExtensionManagement::InstallationMode installation_mode = - settings_->GetInstallationMode(extension); if (installation_mode == ExtensionManagement::INSTALLATION_BLOCKED || installation_mode == ExtensionManagement::INSTALLATION_REMOVED) { #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc index ccecb13..23193649 100644 --- a/chrome/browser/policy/extension_policy_browsertest.cc +++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -373,6 +373,27 @@ extension_prefs->GetDisableReasons( chromeos::default_web_apps::kOsSettingsAppId)); } + +// Ensure that OS Settings is not blocked by the ExtensionAllowedTypes policy. +IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest, ExtensionAllowedTypesOsSettings) { + extensions::ExtensionRegistry* registry = extension_registry(); + const extensions::Extension* bookmark_app = InstallOSSettings(); + ASSERT_TRUE(bookmark_app); + ASSERT_TRUE(registry->enabled_extensions().GetByID( + chromeos::default_web_apps::kOsSettingsAppId)); + + base::ListValue allowed_types; + allowed_types.AppendString("theme"); + PolicyMap policies; + policies.Set(key::kExtensionAllowedTypes, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, + allowed_types.CreateDeepCopy(), nullptr); + UpdateProviderPolicy(policies); + + extensions::ExtensionService* service = extension_service(); + EXPECT_TRUE(service->IsExtensionEnabled( + chromeos::default_web_apps::kOsSettingsAppId)); +} #endif // defined(OS_CHROMEOS) IN_PROC_BROWSER_TEST_F(ExtensionPolicyTest,
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 737d73b..81278d2 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -60,6 +60,10 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chrome_notification_types.h" @@ -238,7 +242,6 @@ #if !defined(OS_MACOSX) #include "base/compiler_specific.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/app_window/native_app_window.h" @@ -1971,8 +1974,9 @@ // Launch an app that tries to open a fullscreen window. TestAddAppWindowObserver add_window_observer( extensions::AppWindowRegistry::Get(browser()->profile())); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), apps::mojom::LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/profiles/independent_otr_profile_manager.cc b/chrome/browser/profiles/independent_otr_profile_manager.cc index 9cfc8a5e..5ef3bbe 100644 --- a/chrome/browser/profiles/independent_otr_profile_manager.cc +++ b/chrome/browser/profiles/independent_otr_profile_manager.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" +#include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" @@ -52,18 +53,17 @@ DCHECK(!callback.is_null()); if (!HasDependentProfiles(original_profile)) observed_original_profiles_.Add(original_profile); - auto* otr_profile = original_profile->CreateOffTheRecordProfile(); + // TODO(https://crbug.com/1033903): Receive profile id from the callers. + std::string profile_id = base::StringPrintf("profile::independent-otr-%i", + first_unused_unique_id_++); + auto* otr_profile = original_profile->GetOffTheRecordProfile( + Profile::OTRProfileID(profile_id)); auto entry = refcounts_map_.emplace(otr_profile, 1); auto callback_entry = callbacks_map_.emplace(otr_profile, std::move(callback)); DCHECK(entry.second); DCHECK(callback_entry.second); - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_PROFILE_CREATED, - content::Source<Profile>(otr_profile), - content::NotificationService::NoDetails()); - return base::WrapUnique(new OTRProfileRegistration(this, otr_profile)); } @@ -101,7 +101,8 @@ } } -IndependentOTRProfileManager::IndependentOTRProfileManager() { +IndependentOTRProfileManager::IndependentOTRProfileManager() + : first_unused_unique_id_(0) { BrowserList::AddObserver(this); }
diff --git a/chrome/browser/profiles/independent_otr_profile_manager.h b/chrome/browser/profiles/independent_otr_profile_manager.h index bb3847b..1d804ae0 100644 --- a/chrome/browser/profiles/independent_otr_profile_manager.h +++ b/chrome/browser/profiles/independent_otr_profile_manager.h
@@ -98,6 +98,10 @@ ScopedObserver<Profile, ProfileObserver> observed_original_profiles_{this}; + // TODO(https://crbug.com/1033903): Remove after getting unique id from + // owners. + int first_unused_unique_id_; + DISALLOW_COPY_AND_ASSIGN(IndependentOTRProfileManager); };
diff --git a/chrome/browser/profiles/independent_otr_profile_manager_browsertest.cc b/chrome/browser/profiles/independent_otr_profile_manager_browsertest.cc index 46cbd9c4..94185d5 100644 --- a/chrome/browser/profiles/independent_otr_profile_manager_browsertest.cc +++ b/chrome/browser/profiles/independent_otr_profile_manager_browsertest.cc
@@ -166,72 +166,6 @@ } IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, - DeleteWaitsForLastBrowser) { - ProfileDestructionWatcher watcher; - Profile* otr_profile = nullptr; - Browser* otr_browser1 = nullptr; - Browser* otr_browser2 = nullptr; - { - auto profile_registration = manager_->CreateFromOriginalProfile( - browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); - otr_profile = profile_registration->profile(); - - otr_browser1 = CreateBrowser(otr_profile); - otr_browser2 = CreateBrowser(otr_profile); - ASSERT_NE(otr_browser1, otr_browser2); - } - - base::RunLoop run_loop1; - BrowserRemovedWaiter removed_waiter1(otr_browser1, - run_loop1.QuitWhenIdleClosure()); - otr_browser1->window()->Close(); - run_loop1.Run(); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser1)); - ASSERT_TRUE(base::Contains(*BrowserList::GetInstance(), otr_browser2)); - - watcher.Watch(otr_profile); - base::RunLoop run_loop2; - BrowserRemovedWaiter removed_waiter2(otr_browser2, - run_loop2.QuitWhenIdleClosure()); - otr_browser2->window()->Close(); - run_loop2.Run(); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser2)); - EXPECT_TRUE(watcher.destroyed()); -} - -IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, - DeleteImmediatelyWhenBrowsersAlreadyClosed) { - ProfileDestructionWatcher watcher; - { - auto profile_registration = manager_->CreateFromOriginalProfile( - browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); - auto* otr_profile = profile_registration->profile(); - - auto* otr_browser1 = CreateBrowser(otr_profile); - auto* otr_browser2 = CreateBrowser(otr_profile); - ASSERT_NE(otr_browser1, otr_browser2); - - base::RunLoop run_loop1; - BrowserRemovedWaiter removed_waiter1(otr_browser1, - run_loop1.QuitWhenIdleClosure()); - base::RunLoop run_loop2; - BrowserRemovedWaiter removed_waiter2(otr_browser2, - run_loop2.QuitWhenIdleClosure()); - otr_browser1->window()->Close(); - otr_browser2->window()->Close(); - run_loop1.Run(); - run_loop2.Run(); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser1)); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser2)); - - watcher.Watch(otr_profile); - } - - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(watcher.destroyed()); -} - -IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, CreateTwoFromSameProfile) { ProfileDestructionWatcher watcher1; ProfileDestructionWatcher watcher2; @@ -312,66 +246,6 @@ EXPECT_TRUE(watcher2.destroyed()); } -IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, - BrowserClosingDoesntRemoveProfileObserver) { - ProfileDestructionWatcher watcher1; - ProfileDestructionWatcher watcher2; - - base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); -#if defined(OS_CHROMEOS) - EnableProfileHelperTestSettings(); -#endif - original_profile_ = Profile::CreateProfile(temp_dir_.GetPath(), nullptr, - Profile::CREATE_MODE_SYNCHRONOUS); - ASSERT_TRUE(original_profile_); - auto profile_owner1 = RegistrationOwner(manager_, original_profile_.get()); - auto* otr_profile1 = profile_owner1.profile(); - Browser* otr_browser = nullptr; - { - auto profile_owner2 = RegistrationOwner(manager_, original_profile_.get()); - auto* otr_profile2 = profile_owner2.profile(); - - otr_browser = CreateBrowser(otr_profile2); - watcher2.Watch(otr_profile2); - } - base::RunLoop run_loop; - BrowserRemovedWaiter removed_waiter(otr_browser, - run_loop.QuitWhenIdleClosure()); - otr_browser->window()->Close(); - run_loop.Run(); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser)); - EXPECT_TRUE(watcher2.destroyed()); - - watcher1.Watch(otr_profile1); - - SafelyDestroyOriginalProfile(); - - EXPECT_TRUE(watcher1.destroyed()); -} - -IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, - CallbackNotCalledAfterUnregister) { - ProfileDestructionWatcher watcher; - Browser* otr_browser = nullptr; - Profile* otr_profile = nullptr; - { - auto profile_registration = manager_->CreateFromOriginalProfile( - browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); - otr_profile = profile_registration->profile(); - - otr_browser = CreateBrowser(otr_profile); - } - watcher.Watch(otr_profile); - base::RunLoop run_loop; - BrowserRemovedWaiter removed_waiter(otr_browser, - run_loop.QuitWhenIdleClosure()); - otr_browser->window()->Close(); - run_loop.Run(); - ASSERT_FALSE(base::Contains(*BrowserList::GetInstance(), otr_browser)); - EXPECT_TRUE(watcher.destroyed()); -} - IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, Notifications) { // Create the OTR profile. content::WindowedNotificationObserver profile_created_observer(
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 16c5fb0..313a0a7a3 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -120,8 +120,11 @@ } // namespace -OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile) +OffTheRecordProfileImpl::OffTheRecordProfileImpl( + Profile* real_profile, + const OTRProfileID& otr_profile_id) : profile_(real_profile), + otr_profile_id_(otr_profile_id), io_data_(this), start_time_(base::Time::Now()), key_(std::make_unique<ProfileKey>(profile_->GetPath(), @@ -295,21 +298,40 @@ return true; } +const Profile::OTRProfileID& OffTheRecordProfileImpl::GetOTRProfileID() const { + return otr_profile_id_; +} + bool OffTheRecordProfileImpl::IsIndependentOffTheRecordProfile() { - return !GetOriginalProfile()->HasOffTheRecordProfile() || - GetOriginalProfile()->GetOffTheRecordProfile() != this; + return otr_profile_id_ != OTRProfileID::PrimaryID(); } -Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile() { - return this; +Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id) { + if (otr_profile_id_ == otr_profile_id) + return this; + return profile_->GetOffTheRecordProfile(otr_profile_id); } -void OffTheRecordProfileImpl::DestroyOffTheRecordProfile() { - // Suicide is bad! +std::vector<Profile*> OffTheRecordProfileImpl::GetAllOffTheRecordProfiles() { + return profile_->GetAllOffTheRecordProfiles(); +} + +void OffTheRecordProfileImpl::DestroyOffTheRecordProfile( + Profile* /*otr_profile*/) { + // OffTheRecord profiles should be destroyed through a request to their + // original profile. NOTREACHED(); } -bool OffTheRecordProfileImpl::HasOffTheRecordProfile() { +bool OffTheRecordProfileImpl::HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id) { + if (otr_profile_id_ == otr_profile_id) + return true; + return profile_->HasOffTheRecordProfile(otr_profile_id); +} + +bool OffTheRecordProfileImpl::HasAnyOffTheRecordProfile() { return true; } @@ -587,7 +609,7 @@ class GuestSessionProfile : public OffTheRecordProfileImpl { public: explicit GuestSessionProfile(Profile* real_profile) - : OffTheRecordProfileImpl(real_profile) { + : OffTheRecordProfileImpl(real_profile, OTRProfileID::PrimaryID()) { set_is_guest_profile(true); } @@ -605,17 +627,19 @@ }; #endif -Profile* Profile::CreateOffTheRecordProfile() { - OffTheRecordProfileImpl* profile = NULL; +// static +std::unique_ptr<Profile> Profile::CreateOffTheRecordProfile( + Profile* parent, + const OTRProfileID& otr_profile_id) { + std::unique_ptr<OffTheRecordProfileImpl> profile; #if defined(OS_CHROMEOS) - if (IsGuestSession()) - profile = new GuestSessionProfile(this); + if (parent->IsGuestSession() && otr_profile_id == OTRProfileID::PrimaryID()) + profile.reset(new GuestSessionProfile(parent)); #endif if (!profile) - profile = new OffTheRecordProfileImpl(this); + profile.reset(new OffTheRecordProfileImpl(parent, otr_profile_id)); profile->Init(); - NotifyOffTheRecordProfileCreated(profile); - return profile; + return std::move(profile); } #if !defined(OS_ANDROID)
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h index 4c34e6c..bdf1358 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.h +++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -37,16 +37,23 @@ //////////////////////////////////////////////////////////////////////////////// class OffTheRecordProfileImpl : public Profile { public: - explicit OffTheRecordProfileImpl(Profile* real_profile); + OffTheRecordProfileImpl(Profile* real_profile, + const OTRProfileID& otr_profile_id); ~OffTheRecordProfileImpl() override; void Init(); // Profile implementation. std::string GetProfileUserName() const override; ProfileType GetProfileType() const override; - Profile* GetOffTheRecordProfile() override; - void DestroyOffTheRecordProfile() override; - bool HasOffTheRecordProfile() override; + // TODO(https://crbug.com/1033903): Remove the default value. + Profile* GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + std::vector<Profile*> GetAllOffTheRecordProfiles() override; + void DestroyOffTheRecordProfile(Profile* otr_profile) override; + // TODO(https://crbug.com/1033903): Remove the default value. + bool HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + bool HasAnyOffTheRecordProfile() override; Profile* GetOriginalProfile() override; const Profile* GetOriginalProfile() const override; bool IsSupervised() const override; @@ -100,6 +107,7 @@ scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override; bool IsOffTheRecord() override; bool IsOffTheRecord() const override; + const OTRProfileID& GetOTRProfileID() const override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::ResourceContext* GetResourceContext() override; content::BrowserPluginGuestManager* GetGuestManager() override; @@ -142,6 +150,8 @@ // The real underlying profile. Profile* profile_; + const OTRProfileID otr_profile_id_; + std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_; #if !defined(OS_ANDROID)
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index 03f65f93..5321cda 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -103,6 +103,24 @@ } // namespace +Profile::OTRProfileID::OTRProfileID(const std::string& profile_id) + : profile_id_(profile_id) {} + +// static +const Profile::OTRProfileID Profile::OTRProfileID::PrimaryID() { + return OTRProfileID("profile::primary_otr"); +} + +const std::string& Profile::OTRProfileID::ToString() const { + return profile_id_; +} + +std::ostream& operator<<(std::ostream& out, + const Profile::OTRProfileID& profile_id) { + out << profile_id.ToString(); + return out; +} + Profile::Profile() : restored_last_session_(false), sent_destroyed_notification_(false), @@ -412,3 +430,10 @@ chrome_variations_client_ = std::make_unique<ChromeVariationsClient>(this); return chrome_variations_client_.get(); } + +void Profile::DestroyOffTheRecordProfile() { + OTRProfileID primary_otr_id = OTRProfileID::PrimaryID(); + if (!HasOffTheRecordProfile(primary_otr_id)) + return; + DestroyOffTheRecordProfile(GetOffTheRecordProfile(primary_otr_id)); +}
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index ee2f1e1b..4b47cd5 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -103,6 +103,39 @@ GUEST_PROFILE, // Guest session's profile }; + class OTRProfileID { + public: + // Creates an OTR profile ID from |profile_id|. + // |profile_id| should follow the following naming scheme: + // "<component>::<subcomponent_id>". For example, "HaTS::WebDialog" + explicit OTRProfileID(const std::string& profile_id); + + // ID used by the incognito and guest profiles. + // TODO(https://crbug.com/1033903): To be replaced with |IncognitoID| and + // |GuestID| when the use cases are reduced. + static const OTRProfileID PrimaryID(); + + bool operator==(const OTRProfileID& other) const { + return profile_id_ == other.profile_id_; + } + + bool operator!=(const OTRProfileID& other) const { + return profile_id_ != other.profile_id_; + } + + bool operator<(const OTRProfileID& other) const { + return profile_id_ < other.profile_id_; + } + + // Returns this OTRProfileID in a string format that can be used for debug + // message. + const std::string& ToString() const; + + private: + OTRProfileID() = default; + const std::string profile_id_; + }; + class Delegate { public: virtual ~Delegate(); @@ -150,6 +183,7 @@ // Note that for Chrome this covers BOTH Incognito mode and Guest sessions. bool IsOffTheRecord() override = 0; virtual bool IsOffTheRecord() const = 0; + virtual const OTRProfileID& GetOTRProfileID() const = 0; variations::VariationsClient* GetVariationsClient() override; @@ -169,27 +203,48 @@ // implementations, this is usually the Google-services email address. virtual std::string GetProfileUserName() const = 0; - // Return the incognito version of this profile. The returned pointer - // is owned by the receiving profile. If the receiving profile is off the - // record, the same profile is returned. + // Return an OffTheRecord version of this profile with the given + // |otr_profile_id|. The returned pointer is owned by the receiving profile. + // If the receiving profile is OffTheRecord, the owner would be its original + // profile. // - // WARNING: This will create the OffTheRecord profile if it doesn't already + // WARNING I: This will create the OffTheRecord profile if it doesn't already // exist. If this isn't what you want, you need to check // HasOffTheRecordProfile() first. - virtual Profile* GetOffTheRecordProfile() = 0; + // + // WARNING II: Once a profile is no longer used, use + // ProfileDestroyer::DestroyProfileWhenAppropriate or + // ProfileDestroyer::DestroyOffTheRecordProfileNow to destroy it. + // + // TODO(https://crbug.com/1033903): Remove the default value. + virtual Profile* GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) = 0; - // Destroys the incognito profile. - virtual void DestroyOffTheRecordProfile() = 0; + // Returns all OffTheRecord profiles. + virtual std::vector<Profile*> GetAllOffTheRecordProfiles() = 0; - // True if an incognito profile exists. - virtual bool HasOffTheRecordProfile() = 0; + // Destroys the OffTheRecord profile. + virtual void DestroyOffTheRecordProfile(Profile* otr_profile) = 0; + + // TODO(https://crbug.com/1033903): Remove this function when all the use + // cases are migrated to above version. The parameter-less version destroys + // the primary OffTheRecord profile. + void DestroyOffTheRecordProfile(); + + // True if an OffTheRecord profile with given id exists. + // TODO(https://crbug.com/1033903): Remove the default value. + virtual bool HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) = 0; + + // Returns true if the profile has any OffTheRecord profiles. + virtual bool HasAnyOffTheRecordProfile() = 0; // Return the original "recording" profile. This method returns this if the - // profile is not incognito. + // profile is not OffTheRecord. virtual Profile* GetOriginalProfile() = 0; // Return the original "recording" profile. This method returns this if the - // profile is not incognito. + // profile is not OffTheRecord. virtual const Profile* GetOriginalProfile() const = 0; // Returns whether the profile is supervised (either a legacy supervised @@ -223,11 +278,15 @@ // Retrieves a pointer to the PrefService that manages the preferences // for OffTheRecord Profiles. This PrefService is lazily created the first // time that this method is called. + // TODO(https://crbug.com/1065444): Investigate whether it's possible to + // remove. virtual PrefService* GetOffTheRecordPrefs() = 0; // Like GetOffTheRecordPrefs but gives a read-only view of prefs that can be // used even if there's no OTR profile at the moment // (i.e. HasOffTheRecordProfile is false). + // TODO(https://crbug.com/1065444): Investigate whether it's possible to + // remove. virtual PrefService* GetReadOnlyOffTheRecordPrefs(); // Returns the main URLLoaderFactory. @@ -236,7 +295,7 @@ // Return whether 2 profiles are the same. 2 profiles are the same if they // represent the same profile. This can happen if there is pointer equality - // or if one profile is the incognito version of another profile (or vice + // or if one profile is the OffTheRecord version of another profile (or vice // versa). virtual bool IsSameProfile(Profile* profile) = 0; @@ -330,14 +389,16 @@ // Returns whether it is an Incognito profile. An Incognito profile is an // off-the-record profile that is not a guest profile. + // + // TODO(https://crbug.com/1033903): Update to return false for non-primary + // OTRs and update documentation above. bool IsIncognitoProfile() const; - // Returns true if this is an off the record profile that is independent from - // its original regular profile. This covers OTR profiles that are directly - // created using CreateOffTheRecordProfile() (such as done by - // IndependentOTRProfileManager). Calling GetOffTheRecordProfile on their - // GetOriginProfile will not point to themselves. - // This type of usage is not recommended. + // Returns true if this is a non-primary OffTheRecord profile. This type of + // OffTheRecord profiles have limited functionality and cannot be used to + // create a browser object. + // + // TODO(https://crbug.com/1033903): Rename to |CanSupportBrowsers|. virtual bool IsIndependentOffTheRecordProfile() = 0; // Returns whether it is a guest session. This covers both the guest profile @@ -407,11 +468,6 @@ // ProfileDestroyer, but in tests, some are not. void MaybeSendDestroyedNotification(); - // Creates an OffTheRecordProfile which points to this Profile. The caller is - // responsible for sending a NOTIFICATION_PROFILE_CREATED when the profile is - // correctly assigned to its owner. - Profile* CreateOffTheRecordProfile(); - #if !defined(OS_ANDROID) // Convenience method to retrieve the default zoom level for the default // storage partition. @@ -435,6 +491,13 @@ is_system_profile_ = is_system_profile; } + // Creates an OffTheRecordProfile which points to this Profile. The caller is + // responsible for sending a NOTIFICATION_PROFILE_CREATED when the profile is + // correctly assigned to its owner. + static std::unique_ptr<Profile> CreateOffTheRecordProfile( + Profile* parent, + const OTRProfileID& otr_profile_id); + // Returns a newly created ExtensionPrefStore suitable for the supplied // Profile. static PrefStore* CreateExtensionPrefStore(Profile*, @@ -472,4 +535,7 @@ bool operator()(Profile* a, Profile* b) const; }; +std::ostream& operator<<(std::ostream& out, + const Profile::OTRProfileID& profile_id); + #endif // CHROME_BROWSER_PROFILES_PROFILE_H_
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc index 67f9e50..92e3e93 100644 --- a/chrome/browser/profiles/profile_browsertest.cc +++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -21,6 +21,7 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" +#include "base/stl_util.h" #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" #include "base/task/thread_pool/thread_pool_instance.h" @@ -33,8 +34,10 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/chrome_version_service.h" +#include "chrome/browser/profiles/profile_destroyer.h" #include "chrome/browser/profiles/profile_impl.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/profiles/profile_observer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_constants.h" @@ -131,6 +134,29 @@ MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool)); }; +class ProfileDestructionWatcher : public ProfileObserver { + public: + ProfileDestructionWatcher() = default; + ~ProfileDestructionWatcher() override = default; + + void Watch(Profile* profile) { observed_profiles_.Add(profile); } + + // ProfileObserver: + void OnProfileWillBeDestroyed(Profile* profile) override { + DCHECK(!destroyed_) << "Double profile destruction"; + destroyed_ = true; + observed_profiles_.Remove(profile); + } + + bool destroyed() const { return destroyed_; } + + private: + bool destroyed_ = false; + ScopedObserver<Profile, ProfileObserver> observed_profiles_{this}; + + DISALLOW_COPY_AND_ASSIGN(ProfileDestructionWatcher); +}; + // Creates a prefs file in the given directory. void CreatePrefsFileInDirectory(const base::FilePath& directory_path) { base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename)); @@ -684,3 +710,106 @@ // let them complete before |temp_dir| goes out of scope. FlushIoTaskRunnerAndSpinThreads(); } + +// Verifies creating an OTR with non-primary id results in a different profile +// from incognito profile. +IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateNonPrimaryOTR) { + Profile::OTRProfileID otr_profile_id("profile::otr"); + + Profile* regular_profile = browser()->profile(); + EXPECT_FALSE(regular_profile->HasAnyOffTheRecordProfile()); + + Profile* otr_profile = + regular_profile->GetOffTheRecordProfile(otr_profile_id); + EXPECT_TRUE(regular_profile->HasAnyOffTheRecordProfile()); + EXPECT_TRUE(otr_profile->IsOffTheRecord()); + EXPECT_EQ(otr_profile_id, otr_profile->GetOTRProfileID()); + EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id)); + EXPECT_NE(otr_profile, regular_profile->GetOffTheRecordProfile( + Profile::OTRProfileID::PrimaryID())); + + regular_profile->DestroyOffTheRecordProfile(otr_profile); + EXPECT_FALSE(regular_profile->HasOffTheRecordProfile(otr_profile_id)); + EXPECT_TRUE(regular_profile->HasOffTheRecordProfile( + Profile::OTRProfileID::PrimaryID())); + EXPECT_TRUE(regular_profile->HasAnyOffTheRecordProfile()); +} + +// Verifies creating two OTRs with different ids results in different profiles. +IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateTwoNonPrimaryOTRs) { + Profile::OTRProfileID otr_profile_id1("profile::otr1"); + Profile::OTRProfileID otr_profile_id2("profile::otr2"); + + Profile* regular_profile = browser()->profile(); + + Profile* otr_profile1 = + regular_profile->GetOffTheRecordProfile(otr_profile_id1); + Profile* otr_profile2 = + regular_profile->GetOffTheRecordProfile(otr_profile_id2); + + EXPECT_NE(otr_profile1, otr_profile2); + EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id1)); + EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id2)); + + regular_profile->DestroyOffTheRecordProfile(otr_profile1); + EXPECT_FALSE(regular_profile->HasOffTheRecordProfile(otr_profile_id1)); + EXPECT_TRUE(regular_profile->HasOffTheRecordProfile(otr_profile_id2)); +} + +// Verifies destroying regular profile will result in destruction of OTR +// profiles. +IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, DestroyRegularProfileBeforeOTRs) { + Profile::OTRProfileID otr_profile_id1("profile::otr1"); + Profile::OTRProfileID otr_profile_id2("profile::otr2"); + + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + MockProfileDelegate delegate; + std::unique_ptr<Profile> regular_profile(CreateProfile( + temp_dir.GetPath(), &delegate, Profile::CREATE_MODE_SYNCHRONOUS)); + + // Creating a profile causes an implicit connection attempt to a Mojo + // service, which occurs as part of a new task. Before deleting |profile|, + // ensure this task runs to prevent a crash. + FlushIoTaskRunnerAndSpinThreads(); + + Profile* otr_profile1 = + regular_profile->GetOffTheRecordProfile(otr_profile_id1); + Profile* otr_profile2 = + regular_profile->GetOffTheRecordProfile(otr_profile_id2); + + ProfileDestructionWatcher watcher1; + ProfileDestructionWatcher watcher2; + watcher1.Watch(otr_profile1); + watcher2.Watch(otr_profile2); + + ProfileDestroyer::DestroyProfileWhenAppropriate(regular_profile.release()); + + EXPECT_TRUE(watcher1.destroyed()); + EXPECT_TRUE(watcher2.destroyed()); +} + +// Tests Profile::GetAllOffTheRecordProfiles +IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, TestGetAllOffTheRecordProfiles) { + Profile::OTRProfileID otr_profile_id1("profile::otr1"); + Profile::OTRProfileID otr_profile_id2("profile::otr2"); + + Profile* regular_profile = browser()->profile(); + + Profile* otr_profile1 = + regular_profile->GetOffTheRecordProfile(otr_profile_id1); + Profile* otr_profile2 = + regular_profile->GetOffTheRecordProfile(otr_profile_id2); + Profile* incognito_profile = regular_profile->GetOffTheRecordProfile( + Profile::OTRProfileID::PrimaryID()); + + std::vector<Profile*> all_otrs = + regular_profile->GetAllOffTheRecordProfiles(); + + EXPECT_EQ(3u, all_otrs.size()); + EXPECT_TRUE(base::Contains(all_otrs, otr_profile1)); + EXPECT_TRUE(base::Contains(all_otrs, otr_profile2)); + EXPECT_TRUE(base::Contains(all_otrs, incognito_profile)); +}
diff --git a/chrome/browser/profiles/profile_destroyer.cc b/chrome/browser/profiles/profile_destroyer.cc index 88c6128e..bcf58358 100644 --- a/chrome/browser/profiles/profile_destroyer.cc +++ b/chrome/browser/profiles/profile_destroyer.cc
@@ -41,7 +41,7 @@ // anyway, so we can't iterate them via AllHostsIterator anyway. if (profile->AsTestingProfile()) { if (profile->IsOffTheRecord()) - profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); + profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile); else delete profile; return; @@ -64,10 +64,7 @@ // hosts referring to it are properly terminated. new ProfileDestroyer(profile, &profile_hosts); } else { - if (profile->IsIndependentOffTheRecordProfile()) - delete profile; - else - profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); + profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile); } return; } @@ -80,6 +77,8 @@ profile_has_off_the_record ? profile->GetOffTheRecordProfile() : nullptr; #endif // DCHECK_IS_ON() + // TODO(https://crbug.com/1033903): If profile has OTRs and they have hosts, + // create a |ProfileDestroyer| instead. delete profile; #if DCHECK_IS_ON() @@ -127,11 +126,7 @@ } } - if (profile->IsIndependentOffTheRecordProfile()) { - delete profile; - } else { - profile->GetOriginalProfile()->DestroyOffTheRecordProfile(); - } + profile->GetOriginalProfile()->DestroyOffTheRecordProfile(profile); } ProfileDestroyer::ProfileDestroyer(Profile* const profile, HostSet* hosts)
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 21cdcfacf..0a75e9d 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -28,6 +28,7 @@ #include "base/no_destructor.h" #include "base/path_service.h" #include "base/sequenced_task_runner.h" +#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -776,16 +777,26 @@ ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this); #endif - // Destroy OTR profile and its profile services first. - if (off_the_record_profile_) { - ProfileDestroyer::DestroyOffTheRecordProfileNow( - off_the_record_profile_.get()); - } else { + // Destroy all OTR profiles and their profile services first. + std::vector<Profile*> raw_otr_profiles; + bool primary_otr_available = false; + + // Get a list of existing OTR profiles since |off_the_record_profile_| might + // be modified after the call to |DestroyOffTheRecordProfileNow|. + for (auto& otr_profile : otr_profiles_) { + raw_otr_profiles.push_back(otr_profile.second.get()); + primary_otr_available |= (otr_profile.first == OTRProfileID::PrimaryID()); + } + + for (Profile* otr_profile : raw_otr_profiles) + ProfileDestroyer::DestroyOffTheRecordProfileNow(otr_profile); + #if BUILDFLAG(ENABLE_EXTENSIONS) + if (!primary_otr_available) { ExtensionPrefValueMapFactory::GetForBrowserContext(this) ->ClearAllIncognitoSessionOnlyPreferences(); -#endif } +#endif FullBrowserTransitionManager::Get()->OnProfileDestroyed(this); @@ -858,33 +869,66 @@ return false; } +const Profile::OTRProfileID& ProfileImpl::GetOTRProfileID() const { + NOTREACHED(); + static base::NoDestructor<OTRProfileID> otr_profile_id( + "ProfileImp::NoOTRProfileID"); + return *otr_profile_id; +} + bool ProfileImpl::IsIndependentOffTheRecordProfile() { return false; } -Profile* ProfileImpl::GetOffTheRecordProfile() { - if (!off_the_record_profile_) { - std::unique_ptr<Profile> p(CreateOffTheRecordProfile()); - off_the_record_profile_.swap(p); +Profile* ProfileImpl::GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id) { + if (HasOffTheRecordProfile(otr_profile_id)) + return otr_profiles_[otr_profile_id].get(); - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_PROFILE_CREATED, - content::Source<Profile>(off_the_record_profile_.get()), - content::NotificationService::NoDetails()); - } - return off_the_record_profile_.get(); + // Create a new OffTheRecordProfile + std::unique_ptr<Profile> otr_profile = + Profile::CreateOffTheRecordProfile(this, otr_profile_id); + Profile* raw_otr_profile = otr_profile.get(); + + otr_profiles_[otr_profile_id] = std::move(otr_profile); + + NotifyOffTheRecordProfileCreated(raw_otr_profile); + + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_PROFILE_CREATED, + content::Source<Profile>(raw_otr_profile), + content::NotificationService::NoDetails()); + + return raw_otr_profile; } -void ProfileImpl::DestroyOffTheRecordProfile() { - off_the_record_profile_.reset(); +std::vector<Profile*> ProfileImpl::GetAllOffTheRecordProfiles() { + std::vector<Profile*> raw_otr_profiles; + for (auto& otr : otr_profiles_) + raw_otr_profiles.push_back(otr.second.get()); + return raw_otr_profiles; +} + +void ProfileImpl::DestroyOffTheRecordProfile(Profile* otr_profile) { + CHECK(otr_profile); + OTRProfileID profile_id = otr_profile->GetOTRProfileID(); + DCHECK(HasOffTheRecordProfile(profile_id)); + otr_profiles_.erase(profile_id); #if BUILDFLAG(ENABLE_EXTENSIONS) - ExtensionPrefValueMapFactory::GetForBrowserContext(this) - ->ClearAllIncognitoSessionOnlyPreferences(); + // Extensions are only supported on primary OTR profile. + if (profile_id == OTRProfileID::PrimaryID()) { + ExtensionPrefValueMapFactory::GetForBrowserContext(this) + ->ClearAllIncognitoSessionOnlyPreferences(); + } #endif } -bool ProfileImpl::HasOffTheRecordProfile() { - return off_the_record_profile_.get() != NULL; +bool ProfileImpl::HasOffTheRecordProfile(const OTRProfileID& otr_profile_id) { + return base::Contains(otr_profiles_, otr_profile_id); +} + +bool ProfileImpl::HasAnyOffTheRecordProfile() { + return !otr_profiles_.empty(); } Profile* ProfileImpl::GetOriginalProfile() { @@ -1297,8 +1341,8 @@ bool ProfileImpl::IsSameProfile(Profile* profile) { if (profile == static_cast<Profile*>(this)) return true; - Profile* otr_profile = off_the_record_profile_.get(); - return otr_profile && profile == otr_profile; + + return profile && profile->GetOriginalProfile() == this; } base::Time ProfileImpl::GetStartTime() const {
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index 326e2e9..6cb65e3 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -114,10 +114,17 @@ base::Time GetCreationTime() const override; bool IsOffTheRecord() override; bool IsOffTheRecord() const override; + const OTRProfileID& GetOTRProfileID() const override; base::FilePath GetPath() const override; - Profile* GetOffTheRecordProfile() override; - void DestroyOffTheRecordProfile() override; - bool HasOffTheRecordProfile() override; + // TODO(https://crbug.com/1033903): Remove the default value. + Profile* GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + std::vector<Profile*> GetAllOffTheRecordProfiles() override; + void DestroyOffTheRecordProfile(Profile* otr_profile) override; + // TODO(https://crbug.com/1033903): Remove the default value. + bool HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + bool HasAnyOffTheRecordProfile() override; Profile* GetOriginalProfile() override; const Profile* GetOriginalProfile() const override; bool IsSupervised() const override; @@ -284,7 +291,7 @@ base::OneShotTimer create_session_service_timer_; #endif - std::unique_ptr<Profile> off_the_record_profile_; + std::map<OTRProfileID, std::unique_ptr<Profile>> otr_profiles_; // See GetStartTime for details. base::Time start_time_;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index bc682e4..5652fbd 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -27,6 +27,10 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/app_mode/app_mode_utils.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/platform_apps/app_load_service.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/browser_process.h" @@ -162,7 +166,6 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/extensions/devtools_util.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" @@ -2690,7 +2693,9 @@ WindowOpenDisposition::CURRENT_TAB, apps::mojom::AppLaunchSource::kSourceContextMenu); launch_params.override_url = params_.link_url; - apps::LaunchService::Get(GetProfile())->OpenApplication(launch_params); + apps::AppServiceProxyFactory::GetForProfile(GetProfile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(launch_params); } void RenderViewContextMenu::ExecProtocolHandler(int event_flags,
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_css.html b/chrome/browser/resources/chromeos/edu_login/edu_login_css.html index c4e89ef3..615dbed 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_css.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_css.html
@@ -8,11 +8,12 @@ font-size: 2em; font-weight: normal; margin-bottom: 16px; - margin-top: 28px; + margin-top: 20px; } p { line-height: 1.5; + margin: 0; white-space: pre-line; }
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html index 098cfeb2..db1456e 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_info.html
@@ -6,8 +6,8 @@ .info-item { display: flex; flex: auto; - padding-bottom: 10px; - padding-top: 10px; + padding-bottom: 16px; + padding-top: 16px; } .info-item:not(:last-child) { @@ -16,11 +16,13 @@ .info-icon { flex-basis: 24px; - padding-top: 10px; } .info-title { + display: flex; flex: 1; + flex-direction: column; + justify-content: center; padding-inline-start: 24px; } </style> @@ -29,8 +31,8 @@ <span slot="main"> <div class="main-padding"> <if expr="_google_chrome"> - <img id="google-full-logo" src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90" - alt=""> + <img class="google-full-logo" + src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90" alt=""> </if> <h1>$i18n{parentInfoTitle}</h1>
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_signin.html b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_signin.html index b59031a..1259845 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_parent_signin.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_parent_signin.html
@@ -8,6 +8,7 @@ display: inline-flex; font-weight: 500; letter-spacing: .25px; + margin-bottom: 16px; max-width: 100%; min-width: 240px; padding: 3px 5px; @@ -44,6 +45,7 @@ .input-group { margin-bottom: 40px; + margin-top: 32px; } .field-wrapper { @@ -136,8 +138,8 @@ <span slot="main"> <div class="main-padding"> <if expr="_google_chrome"> - <img id="google-full-logo" src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90" - alt=""> + <img class="google-full-logo" + src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90" alt=""> </if> <h1>[[getParentSigninTitle_(parent)]]</h1>
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_parents.html b/chrome/browser/resources/chromeos/edu_login/edu_login_parents.html index a9c57b6..f3d84b95 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_parents.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_parents.html
@@ -31,6 +31,10 @@ height: var(--profile-icon-size); width: var(--profile-icon-size); } + + #parentsListBody { + margin-bottom: 16px; + } </style> <edu-login-template> @@ -41,8 +45,8 @@ src="chrome://theme/IDR_LOGO_GOOGLE_COLOR_90" alt=""> </if> <h1>$i18n{parentsListTitle}</h1> - <p id="parentsListBody" aria-hidden="true" class="secondary"> - $i18n{parentsListBody} + <p id="parentsListBody" aria-hidden="true" + class="secondary">$i18n{parentsListBody} </p> </div> <div tabindex="0" role="listbox" aria-labelledby="parentsListBody">
diff --git a/chrome/browser/resources/chromeos/edu_login/edu_login_welcome.html b/chrome/browser/resources/chromeos/edu_login/edu_login_welcome.html index 332ef0b..f6a36e0 100644 --- a/chrome/browser/resources/chromeos/edu_login/edu_login_welcome.html +++ b/chrome/browser/resources/chromeos/edu_login/edu_login_welcome.html
@@ -2,6 +2,7 @@ .main-padding { display: flex; flex-direction: column; + height: calc(100% - 90px); } .image-container {
diff --git a/chrome/browser/resources/chromeos/login/components/progress_list_item.css b/chrome/browser/resources/chromeos/login/components/progress_list_item.css index 5e8a09f..fbf4f21 100644 --- a/chrome/browser/resources/chromeos/login/components/progress_list_item.css +++ b/chrome/browser/resources/chromeos/login/components/progress_list_item.css
@@ -3,7 +3,6 @@ * found in the LICENSE file. */ #container { - align-items: center; height: 56px; } @@ -15,7 +14,7 @@ background-color: var(--google-grey-500); border-radius: 50%; height: 8px; - margin-start: 8px; + margin-inline-start: 8px; width: 8px; }
diff --git a/chrome/browser/resources/chromeos/login/components/progress_list_item.html b/chrome/browser/resources/chromeos/login/components/progress_list_item.html index 67290f1..715cce4 100644 --- a/chrome/browser/resources/chromeos/login/components/progress_list_item.html +++ b/chrome/browser/resources/chromeos/login/components/progress_list_item.html
@@ -25,30 +25,30 @@ --> <dom-module id="progress-list-item"> <template> - <template> - <link rel="stylesheet" href="progress_list_item.css"> - <div class="flex layout horizontal center" id="container"> - <div id="icon"> - <div id="icon-pending" class="dot" - hidden="[[hidePending(active, completed)]]"></div> - <paper-spinner-lite id="icon-active" hidden="[[!active]]"> - </paper-spinner-lite> - <iron-icon id="icon-completed" icon="cr:check" - hidden="[[hideCompleted(active, completed)]]"></iron-icon> + <link rel="stylesheet" href="progress_list_item.css"> + <link rel="stylesheet" href="../oobe_flex_layout.css"> + + <div class="flex layout horizontal center" id="container" role="listitem"> + <div id="icon"> + <div id="icon-pending" class="dot" + hidden="[[hidePending_(active, completed)]]"></div> + <paper-spinner-lite id="icon-active" hidden="[[!active]]" active> + </paper-spinner-lite> + <iron-icon id="icon-completed" icon="cr:check" + hidden="[[hideCompleted_(active, completed)]]"></iron-icon> + </div> + <div id="text" class="content"> + <div id="text-pending" hidden="[[hidePending_(active, completed)]]"> + [[i18nDynamic(locale, textKey)]] </div> - <div id="text" class="content"> - <div id="text-pending" hidden="[[hidePending(active, completed)]]"> - [[i18nDynamic(locale, textKey)]] - </div> - <div id="text-active" hidden="[[!active]]"> - [[fallbackText(locale, activeKey, textKey)]] - </div> - <div id="text-completed" - hidden="[[hideCompleted(active, completed)]]"> - [[fallbackText(locale, completedKey, textKey)]] - </div> + <div id="text-active" hidden="[[!active]]"> + [[fallbackText(locale, activeKey, textKey)]] + </div> + <div id="text-completed" + hidden="[[hideCompleted_(active, completed)]]"> + [[fallbackText(locale, completedKey, textKey)]] </div> </div> - </template> + </div> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/components/progress_list_item.js b/chrome/browser/resources/chromeos/login/components/progress_list_item.js index 6a78d05f..fe10e29 100644 --- a/chrome/browser/resources/chromeos/login/components/progress_list_item.js +++ b/chrome/browser/resources/chromeos/login/components/progress_list_item.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. Polymer({ - is: 'progress-list-element', + is: 'progress-list-item', behaviors: [OobeI18nBehavior],
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html index df3947d11..bc80f846 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -38,6 +38,7 @@ <include src="enterprise_enrollment.html"> <include src="sync_consent.html"> <include src="fingerprint_setup.html"> +<include src="components/progress_list_item.html"> <include src="demo_setup.html"> <include src="demo_preferences.html"> <include src="recommend_apps.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js index f4ce3cc..81cdbab 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -49,6 +49,7 @@ // <include src="enterprise_enrollment.js"> // <include src="sync_consent.js"> // <include src="fingerprint_setup.js"> +// <include src="components/progress_list_item.js"> // <include src="demo_setup.js"> // <include src="demo_preferences.js"> // <include src="recommend_apps.js">
diff --git a/chrome/browser/resources/chromeos/login/demo_setup.css b/chrome/browser/resources/chromeos/login/demo_setup.css index 709f672..f22fd0bc 100644 --- a/chrome/browser/resources/chromeos/login/demo_setup.css +++ b/chrome/browser/resources/chromeos/login/demo_setup.css
@@ -3,7 +3,7 @@ * found in the LICENSE file. */ /* Spinner shown on progress dialog. */ -paper-spinner-lite { +paper-spinner-lite#spinner { height: 164px; width: 164px; }
diff --git a/chrome/browser/resources/chromeos/login/demo_setup.html b/chrome/browser/resources/chromeos/login/demo_setup.html index 5fd028f9..47597a0 100644 --- a/chrome/browser/resources/chromeos/login/demo_setup.html +++ b/chrome/browser/resources/chromeos/login/demo_setup.html
@@ -9,18 +9,28 @@ <hd-iron-icon slot="oobe-icon" icon1x="oobe-32:computer" icon2x="oobe-64:computer"> </hd-iron-icon> - <div slot="footer" class="flex layout vertical center center-justified"> - <div hidden$="[[showProgressBarInDemoModeSetup_]]"> - <paper-spinner-lite id="spinner" dir="ltr" - active></paper-spinner-lite> - </div> - <div hidden$="[[!showProgressBarInDemoModeSetup_]]"> - <!-- TODO(josephkimsh): Confirm UI input for progress bar and - accompanying text. --> - <!-- Paper progress is indeterminate when percentage is 0. --> - <paper-progress indeterminate="[[!progressPercentage_]]" - value="[[progressPercentage_]]"></paper-progress> - <span>Starting up Demo Mode...</span> + <div slot="footer" + class="flex layout vertical center center-justified" + hidden$="[[showStepsInDemoModeSetup_]]"> + <paper-spinner-lite id="spinner" dir="ltr" + active></paper-spinner-lite> + </div> + <div slot="footer" hidden$="[[!showStepsInDemoModeSetup_]]"> + <div id="demo-setup-steps" role="list"> + <progress-list-item text-key="demoSetupProgressStepDownload" + hidden="[[!shouldShowStep_('downloadResources', setupSteps_)]]" + active="[[stepIsActive_( + 'downloadResources', setupSteps_, currentStepIndex_)]]" + completed="[[stepIsCompleted_( + 'downloadResources', setupSteps_, currentStepIndex_)]]"> + </progress-list-item> + <progress-list-item text-key="demoSetupProgressStepEnroll" + hidden="[[!shouldShowStep_('enrollment', setupSteps_)]]" + active="[[stepIsActive_( + 'enrollment', setupSteps_, currentStepIndex_)]]" + completed="[[stepIsCompleted_( + 'enrollment', setupSteps_, currentStepIndex_)]]"> + </progress-list-item> </div> </div> </oobe-dialog>
diff --git a/chrome/browser/resources/chromeos/login/demo_setup.js b/chrome/browser/resources/chromeos/login/demo_setup.js index 40134e2..d755964c 100644 --- a/chrome/browser/resources/chromeos/login/demo_setup.js +++ b/chrome/browser/resources/chromeos/login/demo_setup.js
@@ -13,10 +13,18 @@ behaviors: [OobeI18nBehavior, OobeDialogHostBehavior], properties: { - /** Percentage of progress completed in Demo Mode setup. */ - progressPercentage_: { + /** Object mapping step strings to step indices */ + setupSteps_: { + type: Object, + value() { + return /** @type {!Object} */ (loadTimeData.getValue('demoSetupSteps')); + } + }, + + /** Which step index is currently running in Demo Mode setup. */ + currentStepIndex_: { type: Number, - value: 0, + value: -1, }, /** Error message displayed on demoSetupErrorDialog screen. */ @@ -41,11 +49,11 @@ }, /** Feature flag to display progress bar instead of spinner during setup. */ - showProgressBarInDemoModeSetup_: { + showStepsInDemoModeSetup_: { type: Boolean, readonly: true, value() { - return loadTimeData.getBoolean('showProgressBarInDemoModeSetup'); + return loadTimeData.getBoolean('showStepsInDemoModeSetup'); } } }, @@ -62,17 +70,13 @@ }, /** - * Called when the progress bar needs to be incremented. Every time progress - * is incremented, remaining progress is halved. - * @param {boolean} complete Set to true if progress is complete + * Called at the beginning of a setup step. + * @param {string} currentStep The new step name. */ - incrementSetupProgress(complete) { - const maxPercentage = 100; - if (complete) { - this.progressPercentage_ = maxPercentage; - } else { - const remaining = maxPercentage - this.progressPercentage_; - this.progressPercentage_ += remaining / 2; + setCurrentSetupStep(currentStep) { + // If new step index not specified, remain unchanged. + if (this.setupSteps_.hasOwnProperty(currentStep)) { + this.currentStepIndex_ = this.setupSteps_[currentStep]; } }, @@ -153,4 +157,36 @@ return; chrome.send('login.DemoSetupScreen.userActed', ['close-setup']); }, + + /** + * Whether a given step should be rendered on the UI. + * @param {string} stepName The name of the step (from the enum). + * @param {!Object} setupSteps + * @private + */ + shouldShowStep_(stepName, setupSteps) { + return setupSteps.hasOwnProperty(stepName); + }, + + /** + * Whether a given step is active. + * @param {string} stepName The name of the step (from the enum). + * @param {!Object} setupSteps + * @param {number} currentStepIndex + * @private + */ + stepIsActive_(stepName, setupSteps, currentStepIndex) { + return currentStepIndex == setupSteps[stepName]; + }, + + /** + * Whether a given step is completed. + * @param {string} stepName The name of the step (from the enum). + * @param {!Object} setupSteps + * @param {number} currentStepIndex + * @private + */ + stepIsCompleted_(stepName, setupSteps, currentStepIndex) { + return currentStepIndex > setupSteps[stepName]; + }, });
diff --git a/chrome/browser/resources/chromeos/login/oobe_icons.html b/chrome/browser/resources/chromeos/login/oobe_icons.html index 8bcb30a..e3417915 100644 --- a/chrome/browser/resources/chromeos/login/oobe_icons.html +++ b/chrome/browser/resources/chromeos/login/oobe_icons.html
@@ -58,6 +58,10 @@ <path fill="#1A73E8" fill-rule="nonzero" d="M11.467 22.133l-5.6-5.6L4 18.4l7.467 7.467 16-16L25.6 8z"></path> <path d="M0 0h32v32H0z"></path> </g> + <g id="checkcircle" fill="none" fill-rule="evenodd"> + <path fill="#5BB974" fill-rule="nonzero" d="M 16,2.6667 C 8.6400184,2.6667 2.6667,8.640018 2.6667,16 2.6667,23.359982 8.6400184,29.3333 16,29.3333 23.359982,29.3333 29.3333,23.359982 29.3333,16 29.3333,8.640018 23.359982,2.6667 16,2.6667 Z m 0,23.99994 C 10.120015,26.66664 5.33336,21.879985 5.33336,16 5.33336,10.120015 10.120015,5.33336 16,5.33336 c 5.879985,0 10.66664,4.786655 10.66664,10.66664 0,5.879985 -4.786655,10.66664 -10.66664,10.66664 z M 13.33334,18.933326 9.866682,15.466668 8.00002,17.33333 13.33334,22.66665 23.99998,12.00001 22.133318,10.133348 Z"></path> + <path d="M 0,8 H 24 V 32 H 0 Z"></path> + </g> </defs> </svg> </iron-iconset-svg> @@ -111,10 +115,14 @@ <path style=" stroke:none;fill-rule:nonzero;fill:rgb(35.294118%,35.294118%,35.294118%);fill-opacity:1;" d="M 53.332031 45.332031 C 56.265625 45.332031 58.640625 42.933594 58.640625 40 L 58.667969 13.332031 C 58.667969 10.398438 56.265625 8 53.332031 8 L 10.667969 8 C 7.734375 8 5.332031 10.398438 5.332031 13.332031 L 5.332031 40 C 5.332031 42.933594 7.734375 45.332031 10.667969 45.332031 Z M 10.667969 13.332031 L 53.332031 13.332031 L 53.332031 40 L 10.667969 40 Z M 12.453125 48 L 2.667969 48 L 2.667969 53.332031 L 61.332031 53.332031 L 61.332031 48 L 51.546875 48 "> </path> </g> - <g id="checkmark" fill="none" fill-rule="evenodd"> + <g id="checkmark" fill="none" fill-rule="evenodd"> <path fill="#1A73E8" fill-rule="nonzero" d="M22.933 44.267l-11.2-11.2L8 36.8l14.933 14.933 32-32L51.2 16z"></path> <path d="M0 0h64v64H0z"></path> </g> + <g id="checkcircle" fill="none" fill-rule="evenodd"> + <path fill="#5BB974" fill-rule="nonzero" d="M 32,5.3334 C 17.280037,5.3334 5.3334,17.280036 5.3334,32 5.3334,46.719964 17.280037,58.6666 32,58.6666 46.719964,58.6666 58.6666,46.719964 58.6666,32 58.6666,17.280036 46.719964,5.3334 32,5.3334 Z m 0,47.99988 C 20.24003,53.33328 10.66672,43.75997 10.66672,32 10.66672,20.24003 20.24003,10.66672 32,10.66672 43.75997,10.66672 53.33328,20.24003 53.33328,32 53.33328,43.75997 43.75997,53.33328 32,53.33328 Z M 26.66668,37.866652 19.733364,30.933336 16.00004,34.66666 26.66668,45.3333 47.99996,24.00002 44.266636,20.266696 Z"></path> + <path d="m -14.66665,30.66665 h 48 v 48 h -48 z"></path> + </g> </defs> </svg> </iron-iconset-svg>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_demo_setup.js b/chrome/browser/resources/chromeos/login/oobe_screen_demo_setup.js index 8438640..fecae8e 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_demo_setup.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_demo_setup.js
@@ -8,8 +8,7 @@ login.createScreen('DemoSetupScreen', 'demo-setup', function() { return { - EXTERNAL_API: - ['incrementSetupProgress', 'onSetupSucceeded', 'onSetupFailed'], + EXTERNAL_API: ['setCurrentSetupStep', 'onSetupSucceeded', 'onSetupFailed'], /** * Demo setup module. @@ -39,12 +38,11 @@ }, /** - * Called when the progress bar needs updating with a new percentage value. - * @param {number} percentage Number in range 0-100 denoting progress - * percentage. + * Called at the beginning of a setup step. + * @param {number} currentStepIndex */ - incrementSetupProgress(complete) { - this.demoSetupModule_.incrementSetupProgress(complete); + setCurrentSetupStep(currentStepIndex) { + this.demoSetupModule_.setCurrentSetupStep(currentStepIndex); }, /** Called when demo mode setup succeeded. */
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.js b/chrome/browser/resources/settings/autofill_page/passwords_section.js index 2a9d438..642b427 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.js
@@ -44,6 +44,11 @@ ], properties: { + // <if expr="not chromeos"> + /** @private */ + storedAccounts_: Array, + // </if> + /** Preferences state. */ prefs: { type: Object, @@ -98,7 +103,7 @@ signedIn_: { type: Boolean, value: true, - computed: 'computeSignedIn_(syncStatus_.signedIn)', + computed: 'computeSignedIn_(syncStatus_, storedAccounts_)', }, /** @private */ @@ -299,6 +304,13 @@ syncBrowserProxy.sendSyncPrefsChanged(); this.addWebUIListener('sync-prefs-changed', syncPrefsChanged); + // For non-ChromeOS, also check whether accounts are available. + // <if expr="not chromeos"> + const storedAccountsChanged = accounts => this.storedAccounts_ = accounts; + syncBrowserProxy.getStoredAccounts().then(storedAccountsChanged); + this.addWebUIListener('stored-accounts-updated', storedAccountsChanged); + // </if> + Polymer.RenderStatus.afterNextRender(this, function() { Polymer.IronA11yAnnouncer.requestAvailability(); }); @@ -387,7 +399,9 @@ * @private */ computeSignedIn_() { - return !!this.syncStatus_ && !!this.syncStatus_.signedIn; + return !!this.syncStatus_ && !!this.syncStatus_.signedIn ? + !this.syncStatus_.hasError : + (!!this.storedAccounts_ && this.storedAccounts_.length > 0); }, /**
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html index aed92c9..2c3ef2f2 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html +++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html
@@ -184,10 +184,10 @@ <!-- If this is the Device Account, display the management status --> <template is="dom-if" if="[[item.isDeviceAccount]]"> <cr-tooltip-icon id="primaryAccountTooltip" aria-hidden="true" - icon-class="cr:info-outline" + icon-class="[[getPrimaryAccountTooltipIcon_(isChildUser_)]]" class="tooltip-primary-account" - tooltip-text="$i18n{accountManagerPrimaryAccountTooltip}" - icon-aria-label="$i18n{accountManagerPrimaryAccountTooltip}"> + tooltip-text="[[getPrimaryAccountTooltip_(isChildUser_)]]" + icon-aria-label="[[getPrimaryAccountTooltip_(isChildUser_)]]"> </cr-tooltip-icon> <span class="management-status" aria-labelledby$="fullName-[[index]] email-[[index]]"
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js index d011ced..e56e694 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js +++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
@@ -116,6 +116,24 @@ }, /** + * @return {string} cr icon name. + * @private + */ + getPrimaryAccountTooltipIcon_() { + return this.isChildUser_ ? 'cr20:kite' : 'cr:info-outline'; + }, + + /** + * @return {string} tooltip text + * @private + */ + getPrimaryAccountTooltip_() { + return this.isChildUser_ ? + this.i18n('accountManagerPrimaryAccountChildManagedTooltip') : + this.i18n('accountManagerPrimaryAccountTooltip'); + }, + + /** * @param {string} iconUrl * @return {string} A CSS image-set for multiple scale factors. * @private
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js index 3be79980..2727191 100644 --- a/chrome/browser/resources/settings/chromeos/os_route.js +++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -105,7 +105,7 @@ r.OS_LANGUAGES_INPUT_METHODs = r.OS_LANGUAGES.createChild('/osLanguages/inputMethods'); - r.PRINTING = r.ADVANCED.createSection('/printing', 'printing'); + r.OS_PRINTING = r.ADVANCED.createSection('/osPrinting', 'osPrinting'); r.OS_ACCESSIBILITY = r.ADVANCED.createSection('/osAccessibility', 'a11y'); @@ -150,7 +150,7 @@ r.DATETIME = r.ADVANCED.createSection('/dateTime', 'dateTime'); r.DATETIME_TIMEZONE_SUBPAGE = r.DATETIME.createChild('/dateTime/timeZone'); - r.CUPS_PRINTERS = r.PRINTING.createChild('/cupsPrinters'); + r.CUPS_PRINTERS = r.OS_PRINTING.createChild('/cupsPrinters'); r.MANAGE_ACCESSIBILITY = r.OS_ACCESSIBILITY.createChild('/manageAccessibility');
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html index a322015d..0553a329 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -256,7 +256,7 @@ $i18n{filesPageTitle} </div> </a> - <a href="/printing"> + <a href="/osPrinting"> <div class="item"> <iron-icon icon="cr:print"></iron-icon> $i18n{printingPageTitle}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html index 025514e..ab29cef8 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -239,7 +239,7 @@ </settings-section> </template> <settings-section page-title="$i18n{printingPageTitle}" - section="printing"> + section="osPrinting"> <os-settings-printing-page prefs="{{prefs}}"> </os-settings-printing-page> </settings-section>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js index c9f88ce..dd9fdd4 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -53,6 +53,7 @@ * OS_LANGUAGES: !settings.Route, * OS_LANGUAGES_DETAILS: !settings.Route, * OS_LANGUAGES_INPUT_METHODS: !settings.Route, + * OS_PRINTING: !settings.Route, * OS_RESET: !settings.Route, * OS_SEARCH: !settings.Route, * OS_SYNC: !settings.Route, @@ -63,7 +64,6 @@ * PLUGIN_VM_SHARED_PATHS: !settings.Route, * POINTERS: !settings.Route, * POWER: !settings.Route, - * PRINTING: !settings.Route, * PRIVACY: !settings.Route, * SEARCH: !settings.Route, * RESET: !settings.Route,
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html index bc8700f..4aab97ef 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.html
@@ -23,6 +23,11 @@ label="$i18n{pluginVmPrinterAccess}" pref="{{prefs.plugin_vm.printers_allowed}}"> </settings-toggle-button> + <template is="dom-if" if="[[showPluginVmCamera_]]"> + <settings-toggle-button label="$i18n{pluginVmCameraAccessTitle}" + pref="{{prefs.plugin_vm.camera_sharing}}"> + </settings-toggle-button> + </template> <div id="plugin-vm-remove" class="settings-box"> <div id="pluginVmRemoveLabel" class="start">$i18n{pluginVmRemove}</div> <cr-button on-click="onRemoveClick_" id="pluginVmRemoveButton"
diff --git a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js index a2c70e8..611266c 100644 --- a/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js +++ b/chrome/browser/resources/settings/chromeos/plugin_vm_page/plugin_vm_subpage.js
@@ -24,6 +24,17 @@ type: Boolean, value: false, }, + + /** + * Whether the toggle to share the camera with PluginVm should be shown. + * @private {boolean} + */ + showPluginVmCamera_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('showPluginVmCamera'); + }, + }, }, observers: [
diff --git a/chrome/browser/resources/settings/lazy_load.js b/chrome/browser/resources/settings/lazy_load.js index befa7b77..752aeb1 100644 --- a/chrome/browser/resources/settings/lazy_load.js +++ b/chrome/browser/resources/settings/lazy_load.js
@@ -30,7 +30,6 @@ import './people_page/manage_profile.m.js'; // </if> import './people_page/signout_dialog.m.js'; -import './people_page/sync_account_control.m.js'; import './people_page/sync_controls.m.js'; import './people_page/sync_page.m.js'; @@ -99,6 +98,7 @@ export {CredentialManagementDialogPage} from './privacy_page/security_keys_credential_management_dialog.m.js'; export {BioEnrollDialogPage} from './privacy_page/security_keys_bio_enroll_dialog.m.js'; export {WebsiteUsageBrowserProxyImpl} from './site_settings/website_usage_browser_proxy.m.js'; +export {MAX_SIGNIN_PROMO_IMPRESSION} from './people_page/sync_account_control.m.js'; // <if expr="not chromeos"> export {SystemPageBrowserProxyImpl} from './system_page/system_page_browser_proxy.m.js';
diff --git a/chrome/browser/resources/settings/page_visibility.js b/chrome/browser/resources/settings/page_visibility.js index 49574857..4ddb4ff 100644 --- a/chrome/browser/resources/settings/page_visibility.js +++ b/chrome/browser/resources/settings/page_visibility.js
@@ -119,6 +119,13 @@ // </if> } + /* #export */ function setPageVisibilityForTesting(testVisibility) { + settings.pageVisibility = testVisibility; + } + // #cr_define_end - return {pageVisibility: pageVisibility}; + return { + pageVisibility: pageVisibility, + setPageVisibilityForTesting: setPageVisibilityForTesting, + }; });
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js index a4885f2..84faffd 100644 --- a/chrome/browser/resources/settings/people_page/sync_account_control.js +++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -8,7 +8,7 @@ */ cr.define('settings', function() { /** @const {number} */ - const MAX_SIGNIN_PROMO_IMPRESSION = 10; + /* #export */ const MAX_SIGNIN_PROMO_IMPRESSION = 10; Polymer({ is: 'settings-sync-account-control',
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index 6c10820..8a14db1 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -228,7 +228,7 @@ /** * @return {!settings.Router} A router with the browser settings routes. */ - function buildRouter() { + /* #export */ function buildRouter() { return new settings.Router(createBrowserSettingsRoutes()); }
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js index 93dd7a9..ae17b8c 100644 --- a/chrome/browser/resources/settings/settings.js +++ b/chrome/browser/resources/settings/settings.js
@@ -52,12 +52,12 @@ export {OpenWindowProxyImpl} from './open_window_proxy.m.js'; export {PageStatus, StatusAction, SyncBrowserProxyImpl} from './people_page/sync_browser_proxy.m.js'; export {ProfileInfoBrowserProxyImpl} from './people_page/profile_info_browser_proxy.m.js'; -export {pageVisibility} from './page_visibility.m.js'; +export {pageVisibility, setPageVisibilityForTesting} from './page_visibility.m.js'; export {PasswordManagerProxy, PasswordManagerImpl} from './autofill_page/password_manager_proxy.m.js'; export {PluralStringProxyImpl} from './plural_string_proxy.m.js'; export {prefToString, stringToPrefValue} from './prefs/pref_util.m.js'; export {ResetBrowserProxyImpl} from './reset_page/reset_browser_proxy.m.js'; -export {routes} from './route.m.js'; +export {buildRouter, routes} from './route.m.js'; export {Route, Router} from './router.m.js'; export {SearchEnginesBrowserProxyImpl} from './search_engines_page/search_engines_browser_proxy.m.js'; export {PrivacyPageBrowserProxyImpl, SecureDnsMode, SecureDnsUiManagementMode} from './privacy_page/privacy_page_browser_proxy.m.js';
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc index 76925c17..981d34e 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc
@@ -173,11 +173,22 @@ ? response.dlp_scan_verdict().status() == DlpDeepScanningVerdict::SUCCESS : true; - bool malware_verdict_success = - response.has_malware_scan_verdict() - ? response.malware_scan_verdict().verdict() != - MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED - : true; + + bool malware_verdict_success = true; + if (response.has_malware_scan_verdict()) { + switch (response.malware_scan_verdict().verdict()) { + case MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED: + case MalwareDeepScanningVerdict::SCAN_FAILURE: + malware_verdict_success = false; + break; + case MalwareDeepScanningVerdict::MALWARE: + case MalwareDeepScanningVerdict::UWS: + case MalwareDeepScanningVerdict::CLEAN: + malware_verdict_success = true; + break; + } + } + bool success = dlp_verdict_success && malware_verdict_success; std::string result_value = BinaryUploadServiceResultToString(result, success);
diff --git a/chrome/browser/sharing/sharing_metrics.cc b/chrome/browser/sharing/sharing_metrics.cc index 6e5f964..7240686 100644 --- a/chrome/browser/sharing/sharing_metrics.cc +++ b/chrome/browser/sharing/sharing_metrics.cc
@@ -399,6 +399,11 @@ base::StrCat( {metric_prefix, ".", PulseIntervalToString(pulse_interval)}), result); + base::UmaHistogramEnumeration( + base::StrCat({metric_prefix, ".", + DevicePlatformToString(receiving_device_platform), ".", + PulseIntervalToString(pulse_interval)}), + result); } }
diff --git a/chrome/browser/supervised_user/supervised_user_constants.cc b/chrome/browser/supervised_user/supervised_user_constants.cc index cd21497..dc6e883 100644 --- a/chrome/browser/supervised_user/supervised_user_constants.cc +++ b/chrome/browser/supervised_user/supervised_user_constants.cc
@@ -10,9 +10,6 @@ const char kAccountConsistencyMirrorRequired[] = "AccountConsistencyMirrorRequired"; #endif -#if BUILDFLAG(ENABLE_EXTENSIONS) -const char kApprovedExtensions[] = "ApprovedExtensions"; -#endif const char kAuthorizationHeaderFormat[] = "Bearer %s"; const char kCameraMicDisabled[] = "CameraMicDisabled"; const char kContentPackDefaultFilteringBehavior[] =
diff --git a/chrome/browser/supervised_user/supervised_user_constants.h b/chrome/browser/supervised_user/supervised_user_constants.h index d7cbb19..26c8ea5 100644 --- a/chrome/browser/supervised_user/supervised_user_constants.h +++ b/chrome/browser/supervised_user/supervised_user_constants.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_CONSTANTS_H_ #define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_CONSTANTS_H_ -#include "extensions/buildflags/buildflags.h" - namespace supervised_users { // Keys for supervised user settings. These are configured remotely and mapped @@ -14,9 +12,6 @@ #if defined(OS_CHROMEOS) extern const char kAccountConsistencyMirrorRequired[]; #endif -#if BUILDFLAG(ENABLE_EXTENSIONS) -extern const char kApprovedExtensions[]; -#endif extern const char kAuthorizationHeaderFormat[]; extern const char kCameraMicDisabled[]; extern const char kContentPackDefaultFilteringBehavior[];
diff --git a/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.cc b/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.cc index 409e807..d247b34dc 100644 --- a/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.cc +++ b/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.cc
@@ -19,16 +19,16 @@ // static void SupervisedUserExtensionsMetricsRecorder::RecordExtensionsUmaMetrics( - syncer::SyncChange::SyncChangeType type) { + SupervisedUserService::ApprovedExtensionChange type) { switch (type) { - case syncer::SyncChange::ACTION_ADD: + case SupervisedUserService::ApprovedExtensionChange::kNew: // Record UMA metrics for custodian approval for a new extension. base::RecordAction( base::UserMetricsAction(kNewExtensionApprovalGrantedActionName)); base::UmaHistogramEnumeration( kHistogramName, UmaExtensionState::kNewExtensionApprovalGranted); break; - case syncer::SyncChange::ACTION_UPDATE: + case SupervisedUserService::ApprovedExtensionChange::kUpdate: // Record UMA metrics for child approval for a newer version of an // existing extension. base::RecordAction( @@ -36,14 +36,11 @@ base::UmaHistogramEnumeration( kHistogramName, UmaExtensionState::kNewVersionApprovalGranted); break; - case syncer::SyncChange::ACTION_DELETE: + case SupervisedUserService::ApprovedExtensionChange::kRemove: // Record UMA metrics for removing an extension. base::RecordAction(base::UserMetricsAction(kRemovedActionName)); base::UmaHistogramEnumeration(kHistogramName, UmaExtensionState::kRemoved); break; - case syncer::SyncChange::ACTION_INVALID: - NOTREACHED(); - break; } }
diff --git a/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h b/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h index 2c09e93..734c1d8a 100644 --- a/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h +++ b/chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_METRICS_RECORDER_H_ #define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_METRICS_RECORDER_H_ -#include "components/sync/model/sync_change.h" +#include "chrome/browser/supervised_user/supervised_user_service.h" // Records UMA metrics for child users using extensions. // TODO(tobyhuang): Reevaluate if this class should be converted to a namespace @@ -38,7 +38,7 @@ const SupervisedUserExtensionsMetricsRecorder&) = delete; static void RecordExtensionsUmaMetrics( - syncer::SyncChange::SyncChangeType type); + SupervisedUserService::ApprovedExtensionChange type); }; #endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_EXTENSIONS_METRICS_RECORDER_H_
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc index 966cdd7..462bfa9 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -52,16 +52,20 @@ prefs::kSupervisedUserManualURLs, }, { - supervised_users::kForceSafeSearch, prefs::kForceGoogleSafeSearch, + supervised_users::kForceSafeSearch, + prefs::kForceGoogleSafeSearch, }, { - supervised_users::kSafeSitesEnabled, prefs::kSupervisedUserSafeSites, + supervised_users::kSafeSitesEnabled, + prefs::kSupervisedUserSafeSites, }, { - supervised_users::kSigninAllowed, prefs::kSigninAllowed, + supervised_users::kSigninAllowed, + prefs::kSigninAllowed, }, { - supervised_users::kUserName, prefs::kProfileName, + supervised_users::kUserName, + prefs::kProfileName, }, };
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index ae5d2d8..d5c4e9574 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -19,6 +19,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" +#include "base/values.h" #include "base/version.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -27,7 +28,6 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h" #include "chrome/browser/supervised_user/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_filtering_switches.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" @@ -67,6 +67,7 @@ #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" #endif @@ -126,6 +127,9 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) registry->RegisterBooleanPref( prefs::kSupervisedUserExtensionsMayRequestPermissions, false); + registry->RegisterDictionaryPref( + prefs::kSupervisedUserApprovedExtensions, + user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); #endif registry->RegisterDictionaryPref(prefs::kSupervisedUserManualHosts); registry->RegisterDictionaryPref(prefs::kSupervisedUserManualURLs); @@ -326,60 +330,27 @@ } #if BUILDFLAG(ENABLE_EXTENSIONS) -void SupervisedUserService::AddExtensionApproval( +void SupervisedUserService::AddOrUpdateExtensionApproval( const extensions::Extension& extension) { - UpdateApprovedExtensions(extension.id(), extension.VersionString(), - syncer::SyncChange::SyncChangeType::ACTION_ADD); + bool has_key = base::Contains(approved_extensions_map_, extension.id()); + ApprovedExtensionChange update_type = has_key + ? ApprovedExtensionChange::kUpdate + : ApprovedExtensionChange::kNew; + UpdateApprovedExtension(extension.id(), extension.VersionString(), + update_type); } void SupervisedUserService::RemoveExtensionApproval( const extensions::Extension& extension) { - UpdateApprovedExtensions(extension.id(), extension.VersionString(), - syncer::SyncChange::SyncChangeType::ACTION_DELETE); + UpdateApprovedExtension(extension.id(), extension.VersionString(), + ApprovedExtensionChange::kRemove); } -void SupervisedUserService::UpdateApprovedExtensions( +void SupervisedUserService::UpdateApprovedExtensionForTesting( const std::string& extension_id, const std::string& version, - syncer::SyncChange::SyncChangeType type) { - std::string key = SupervisedUserSettingsService::MakeSplitSettingKey( - supervised_users::kApprovedExtensions, extension_id); - syncer::SyncData sync_data = - SupervisedUserSettingsService::CreateSyncDataForSetting( - key, base::Value(version)); - - syncer::SyncChangeList list(1, - syncer::SyncChange(FROM_HERE, type, sync_data)); - GetSettingsService()->ProcessSyncChanges(FROM_HERE, list); - - // Keep track of currently approved extensions. We may need to disable them if - // they are not in the approved map anymore. - std::set<std::string> extensions_to_be_checked; - for (const auto& extension : approved_extensions_map_) - extensions_to_be_checked.insert(extension.first); - - approved_extensions_map_.clear(); - - const base::DictionaryValue* dict = - GetSettingsService()->GetDictionaryAndSplitKey(&key); - for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { - std::string version_str; - bool result = it.value().GetAsString(&version_str); - DCHECK(result); - base::Version version(version_str); - if (version.IsValid()) { - approved_extensions_map_[it.key()] = version; - extensions_to_be_checked.insert(it.key()); - } else { - LOG(WARNING) << "Invalid version number " << version_str; - } - } - - for (const auto& extension_id : extensions_to_be_checked) { - ChangeExtensionStateIfNecessary(extension_id); - } - - SupervisedUserExtensionsMetricsRecorder::RecordExtensionsUmaMetrics(type); + ApprovedExtensionChange type) { + UpdateApprovedExtension(extension_id, version, type); } bool SupervisedUserService:: @@ -446,6 +417,12 @@ base::BindRepeating( &SupervisedUserService::OnDefaultFilteringBehaviorChanged, base::Unretained(this))); +#if BUILDFLAG(ENABLE_EXTENSIONS) + pref_change_registrar_.Add( + prefs::kSupervisedUserApprovedExtensions, + base::BindRepeating(&SupervisedUserService::UpdateApprovedExtensions, + base::Unretained(this))); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) pref_change_registrar_.Add( prefs::kSupervisedUserSafeSites, base::BindRepeating(&SupervisedUserService::OnSafeSitesSettingChanged, @@ -472,6 +449,10 @@ UpdateManualHosts(); UpdateManualURLs(); +#if BUILDFLAG(ENABLE_EXTENSIONS) + UpdateApprovedExtensions(); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + #if !defined(OS_ANDROID) // TODO(bauerb): Get rid of the platform-specific #ifdef here. // http://crbug.com/313377 @@ -482,6 +463,9 @@ pref_change_registrar_.Remove( prefs::kDefaultSupervisedUserFilteringBehavior); +#if BUILDFLAG(ENABLE_EXTENSIONS) + pref_change_registrar_.Remove(prefs::kSupervisedUserApprovedExtensions); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) pref_change_registrar_.Remove(prefs::kSupervisedUserManualHosts); pref_change_registrar_.Remove(prefs::kSupervisedUserManualURLs); for (const char* pref : kCustodianInfoPrefs) { @@ -510,6 +494,12 @@ profile_->GetProfileKey()); } +PrefService* SupervisedUserService::GetPrefService() { + PrefService* pref_service = profile_->GetPrefs(); + DCHECK(pref_service) << "PrefService not found"; + return pref_service; +} + size_t SupervisedUserService::FindEnabledPermissionRequestCreator( size_t start) { for (size_t i = start; i < permissions_creators_.size(); ++i) { @@ -702,11 +692,11 @@ const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualHosts); std::map<std::string, bool> host_map; - for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { + for (auto it : dict->DictItems()) { bool allow = false; - bool result = it.value().GetAsBoolean(&allow); + bool result = it.second.GetAsBoolean(&allow); DCHECK(result); - host_map[it.key()] = allow; + host_map[it.first] = allow; } url_filter_.SetManualHosts(std::move(host_map)); @@ -718,11 +708,11 @@ const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary(prefs::kSupervisedUserManualURLs); std::map<GURL, bool> url_map; - for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { + for (auto it : dict->DictItems()) { bool allow = false; - bool result = it.value().GetAsBoolean(&allow); + bool result = it.second.GetAsBoolean(&allow); DCHECK(result); - url_map[GURL(it.key())] = allow; + url_map[GURL(it.first)] = allow; } url_filter_.SetManualURLs(std::move(url_map)); @@ -890,10 +880,8 @@ id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE) && approved_extensions_map_.count(id) > 0 && approved_extensions_map_[id] < version) { - approved_extensions_map_[id] = version; - - UpdateApprovedExtensions(id, version.GetString(), - syncer::SyncChange::ACTION_ADD); + UpdateApprovedExtension(id, version.GetString(), + ApprovedExtensionChange::kUpdate); } else { // Upon extension update, the approved version may (or may not) match the // installed one. Therefore, a change in extension state might be required. @@ -955,6 +943,60 @@ } } +void SupervisedUserService::UpdateApprovedExtension( + const std::string& extension_id, + const std::string& version, + ApprovedExtensionChange type) { + PrefService* pref_service = GetPrefService(); + DictionaryPrefUpdate update(pref_service, + prefs::kSupervisedUserApprovedExtensions); + base::DictionaryValue* approved_extensions = update.Get(); + DCHECK(approved_extensions) + << "kSupervisedUserApprovedExtensions pref not found"; + switch (type) { + case ApprovedExtensionChange::kNew: + case ApprovedExtensionChange::kUpdate: + approved_extensions->SetStringKey(extension_id, std::move(version)); + break; + case ApprovedExtensionChange::kRemove: + approved_extensions->RemoveKey(extension_id); + break; + } + + SupervisedUserExtensionsMetricsRecorder::RecordExtensionsUmaMetrics(type); +} + +void SupervisedUserService::UpdateApprovedExtensions() { + // Keep track of currently approved extensions. We need to disable them if + // they are not in the approved map anymore. + std::set<std::string> extensions_to_be_checked; + for (const auto& extension : approved_extensions_map_) + extensions_to_be_checked.insert(extension.first); + + // The purpose here is to re-populate the approved_extensions_map_, which is + // used in GetExtensionState() to keep track of approved extensions. + approved_extensions_map_.clear(); + + const base::DictionaryValue* dict = profile_->GetPrefs()->GetDictionary( + prefs::kSupervisedUserApprovedExtensions); + for (auto it : dict->DictItems()) { + std::string version_str; + bool result = it.second.GetAsString(&version_str); + DCHECK(result); + base::Version version(version_str); + if (version.IsValid()) { + approved_extensions_map_[it.first] = version; + extensions_to_be_checked.insert(it.first); + } else { + LOG(WARNING) << "Invalid version number " << version_str; + } + } + + for (const auto& extension_id : extensions_to_be_checked) { + ChangeExtensionStateIfNecessary(extension_id); + } +} + void SupervisedUserService::SetExtensionsActive() { extensions::ExtensionSystem* extension_system = extensions::ExtensionSystem::Get(profile_);
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h index 4df2171c..e33462e 100644 --- a/chrome/browser/supervised_user/supervised_user_service.h +++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -32,7 +32,6 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "base/strings/string16.h" #include "chrome/browser/ui/supervised_user/parent_permission_dialog.h" -#include "components/sync/model/sync_change.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/management_policy.h" @@ -40,6 +39,7 @@ class Browser; class PermissionRequestCreator; +class PrefService; class Profile; class SupervisedUserServiceObserver; class SupervisedUserSettingsService; @@ -86,6 +86,20 @@ virtual bool SetActive(bool active) = 0; }; +#if BUILDFLAG(ENABLE_EXTENSIONS) + // These enum values represent operations to manage the + // kSupervisedUserApprovedExtensions user pref, which maps extension ids to + // approved versions. + enum class ApprovedExtensionChange { + // Adds a new approved extension to the pref. + kNew, + // Updates the version of an already-approved extension. + kUpdate, + // Removes extension approval. + kRemove + }; +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + ~SupervisedUserService() override; static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -191,20 +205,19 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) // Updates the map of approved extensions to add approval for |extension|. - void AddExtensionApproval(const extensions::Extension& extension); + void AddOrUpdateExtensionApproval(const extensions::Extension& extension); // Updates the map of approved extensions to remove approval for |extension|. void RemoveExtensionApproval(const extensions::Extension& extension); - // Updates the map of approved extensions. - // If possible, use the simpler methods declared above. - // If |type| is SyncChangeType::ADD, then add custodian approval for enabling - // the extension by adding the approved version to the map of approved - // extensions. If |type| is SyncChangeType::DELETE, then remove the extension - // from the map of approved extensions. - void UpdateApprovedExtensions(const std::string& extension_id, - const std::string& version, - syncer::SyncChange::SyncChangeType type); + // Simulates a custodian or child approval for enabling the extension coming + // in through Sync by adding the approved version to the map of approved + // extensions. Removes approval by passing in + // ApprovedExtensionChange::kRemove. It doesn't simulate a change in the + // disable reasons. + void UpdateApprovedExtensionForTesting(const std::string& extension_id, + const std::string& version, + ApprovedExtensionChange type); bool GetSupervisedUserExtensionsMayRequestPermissionsPref() const; @@ -276,16 +289,37 @@ // "Permissions for sites, apps and extensions" toggle. bool ShouldBlockExtension(const std::string& extension_id) const; - // Extensions helper to SetActive(). - void SetExtensionsActive(); - // Enables/Disables extensions upon change in approved version of the // extension_id. This function is idempotent. void ChangeExtensionStateIfNecessary(const std::string& extension_id); + + // Updates the map of approved extensions. + // Use AddOrUpdateExtensionApproval() or RemoveExtensionApproval() for public + // access. + // If |type| is kNew, then adds custodian approval for enabling the extension + // by adding the approved version to the map of approved extensions. + // If |type| is kUpdate, then updates the approved version for the extension + // in the map. + // If |type| is kRemove, then removes the extension from the map of approved + // extensions. + void UpdateApprovedExtension(const std::string& extension_id, + const std::string& version, + ApprovedExtensionChange type); + + // Updates the map of approved extensions when the corresponding preference is + // changed. + void UpdateApprovedExtensions(); + + // Extensions helper to SetActive(). + void SetExtensionsActive(); #endif // BUILDFLAG(ENABLE_EXTENSIONS) + // Returns the SupervisedUserSettingsService associated with |profile_|. SupervisedUserSettingsService* GetSettingsService(); + // Returns the PrefService associated with |profile_|. + PrefService* GetPrefService(); + size_t FindEnabledPermissionRequestCreator(size_t start); void AddPermissionRequestInternal( const CreatePermissionRequestCallback& create_request,
diff --git a/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.cc b/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.cc index 7e5f548f..e478c3f 100644 --- a/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.cc +++ b/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h" #include <utility> +#include <vector> #include "ash/public/cpp/ambient/ambient_prefs.h" #include "base/base64.h" @@ -157,8 +158,23 @@ void PhotoClientImpl::FetchTopicInfo(OnTopicInfoFetchedCallback callback) { // TODO(b/148463064): Access token will be requested and cached before // entering lock screen. + // Consolidate the functions of StartToFetchTopicInfo, StartToGetSettings, and + // StartToUpdateSettings after this is done. RequestAccessToken(base::BindOnce(&PhotoClientImpl::StartToFetchTopicInfo, - base::Unretained(this), + weak_factory_.GetWeakPtr(), + std::move(callback))); +} + +void PhotoClientImpl::GetSettings(GetSettingsCallback callback) { + RequestAccessToken(base::BindOnce(&PhotoClientImpl::StartToGetSettings, + weak_factory_.GetWeakPtr(), + std::move(callback))); +} + +void PhotoClientImpl::UpdateSettings(int topic_source, + UpdateSettingsCallback callback) { + RequestAccessToken(base::BindOnce(&PhotoClientImpl::StartToUpdateSettings, + weak_factory_.GetWeakPtr(), topic_source, std::move(callback))); } @@ -172,6 +188,8 @@ signin::ScopeSet scopes; scopes.insert(kPhotosOAuthScope); // TODO(b/148463064): Handle retry refresh token and multiple requests. + // Currently only one request is allowed. + DCHECK(!access_token_fetcher_); access_token_fetcher_ = identity_manager->CreateAccessTokenFetcherForAccount( account_info.account_id, /*oauth_consumer_name=*/"ChromeOS_AmbientMode", @@ -186,45 +204,22 @@ signin::AccessTokenInfo access_token_info) { access_token_fetcher_.reset(); if (gaia_id.empty() || access_token_info.token.empty()) { - std::move(callback).Run(/*success=*/false, base::nullopt); + std::move(callback).Run(base::nullopt); return; } std::string client_id = GetClientId(); chromeos::ambient::BackdropClientConfig::Request request = - backdrop_client_config_.GetFetchTopicInfoRequest( + backdrop_client_config_.CreateFetchTopicInfoRequest( gaia_id, access_token_info.token, client_id); auto resource_request = CreateResourceRequest(request); - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("backdrop_fetch_topics", - R"( - semantics { - sender: "ChromeOS Ambient Mode" - description: - "The ChromeOS Ambient Mode displays a rich set of photos for " - "users to choose from." - trigger: - "When ChromeOS Ambient Mode starts" - data: - "The Backdrop protocol buffer messages. Containing user auth" - "token and a unique random client id." - destination: GOOGLE_OWNED_SERVICE - } - policy { - cookies_allowed: NO - setting: - "NA" - policy_exception_justification: - "Not implemented, considered not necessary." - })"); - // |base::Unretained| is safe because this instance outlives // |backdrop_url_loader_|. DCHECK(!backdrop_url_loader_); backdrop_url_loader_ = std::make_unique<BackdropURLLoader>(); backdrop_url_loader_->Start( - std::move(resource_request), request.body, traffic_annotation, + std::move(resource_request), request.body, NO_TRAFFIC_ANNOTATION_YET, base::BindOnce(&PhotoClientImpl::OnTopicInfoFetched, base::Unretained(this), std::move(callback))); } @@ -239,5 +234,84 @@ backdrop::ScreenUpdate::Topic backdrop_topic = BackdropClientConfig::ParseFetchTopicInfoResponse(*response); ash::PhotoController::Topic topic = CreateTopicFrom(backdrop_topic); - std::move(callback).Run(/*success=*/true, topic); + std::move(callback).Run(topic); +} + +void PhotoClientImpl::StartToGetSettings( + GetSettingsCallback callback, + const std::string& gaia_id, + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info) { + access_token_fetcher_.reset(); + + if (gaia_id.empty() || access_token_info.token.empty()) { + std::move(callback).Run(/*topic_source=*/base::nullopt); + return; + } + + std::string client_id = GetClientId(); + BackdropClientConfig::Request request = + backdrop_client_config_.CreateGetSettingsRequest( + gaia_id, access_token_info.token, client_id); + auto resource_request = CreateResourceRequest(request); + + // |base::Unretained| is safe because this instance outlives + // |backdrop_url_loader_|. + DCHECK(!backdrop_url_loader_); + backdrop_url_loader_ = std::make_unique<BackdropURLLoader>(); + backdrop_url_loader_->Start( + std::move(resource_request), request.body, NO_TRAFFIC_ANNOTATION_YET, + base::BindOnce(&PhotoClientImpl::OnGetSettings, base::Unretained(this), + std::move(callback))); +} + +void PhotoClientImpl::OnGetSettings(GetSettingsCallback callback, + std::unique_ptr<std::string> response) { + DCHECK(backdrop_url_loader_); + backdrop_url_loader_.reset(); + + int topic_source = BackdropClientConfig::ParseGetSettingsResponse(*response); + if (topic_source == -1) + std::move(callback).Run(base::nullopt); + else + std::move(callback).Run(topic_source); +} + +void PhotoClientImpl::StartToUpdateSettings( + int topic_source, + UpdateSettingsCallback callback, + const std::string& gaia_id, + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info) { + access_token_fetcher_.reset(); + + if (gaia_id.empty() || access_token_info.token.empty()) { + std::move(callback).Run(/*success=*/false); + return; + } + + std::string client_id = GetClientId(); + BackdropClientConfig::Request request = + backdrop_client_config_.CreateUpdateSettingsRequest( + gaia_id, access_token_info.token, client_id, topic_source); + auto resource_request = CreateResourceRequest(request); + + // |base::Unretained| is safe because this instance outlives + // |backdrop_url_loader_|. + DCHECK(!backdrop_url_loader_); + backdrop_url_loader_ = std::make_unique<BackdropURLLoader>(); + backdrop_url_loader_->Start( + std::move(resource_request), request.body, NO_TRAFFIC_ANNOTATION_YET, + base::BindOnce(&PhotoClientImpl::OnUpdateSettings, base::Unretained(this), + std::move(callback))); +} + +void PhotoClientImpl::OnUpdateSettings(UpdateSettingsCallback callback, + std::unique_ptr<std::string> response) { + DCHECK(backdrop_url_loader_); + backdrop_url_loader_.reset(); + + const bool success = + BackdropClientConfig::ParseUpdateSettingsResponse(*response); + std::move(callback).Run(success); }
diff --git a/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h b/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h index 0b248fb..b0729a0 100644 --- a/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h +++ b/chrome/browser/ui/ash/ambient/backdrop/photo_client_impl.h
@@ -7,7 +7,7 @@ #include <memory> -#include "base/callback.h" +#include "ash/public/cpp/ambient/photo_controller.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/ash/ambient/photo_client.h" #include "chromeos/assistant/internal/ambient/backdrop_client_config.h" @@ -23,15 +23,22 @@ // The photo client impl talks to Backdrop service. class PhotoClientImpl : public PhotoClient { public: + using GetSettingsCallback = ash::PhotoController::GetSettingsCallback; + using UpdateSettingsCallback = ash::PhotoController::UpdateSettingsCallback; + PhotoClientImpl(); - ~PhotoClientImpl() override; PhotoClientImpl(const PhotoClientImpl&) = delete; PhotoClientImpl& operator=(const PhotoClientImpl&) = delete; + ~PhotoClientImpl() override; // PhotoClient: void FetchTopicInfo(OnTopicInfoFetchedCallback callback) override; + void GetSettings(GetSettingsCallback callback) override; + void UpdateSettings(int topic_source, + UpdateSettingsCallback callback) override; private: + using BackdropClientConfig = chromeos::ambient::BackdropClientConfig; using GetAccessTokenCallback = base::OnceCallback<void(const std::string& gaia_id, GoogleServiceAuthError error, @@ -47,12 +54,29 @@ void OnTopicInfoFetched(OnTopicInfoFetchedCallback callback, std::unique_ptr<std::string> response); + void StartToGetSettings(GetSettingsCallback callback, + const std::string& gaia_id, + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info); + + void OnGetSettings(GetSettingsCallback callback, + std::unique_ptr<std::string> response); + + void StartToUpdateSettings(int topic_sources, + UpdateSettingsCallback callback, + const std::string& gaia_id, + GoogleServiceAuthError error, + signin::AccessTokenInfo access_token_info); + + void OnUpdateSettings(UpdateSettingsCallback callback, + std::unique_ptr<std::string> response); + // The url loader for the Backdrop service request. std::unique_ptr<BackdropURLLoader> backdrop_url_loader_; std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_; - chromeos::ambient::BackdropClientConfig backdrop_client_config_; + BackdropClientConfig backdrop_client_config_; base::WeakPtrFactory<PhotoClientImpl> weak_factory_{this}; };
diff --git a/chrome/browser/ui/ash/ambient/photo_client.cc b/chrome/browser/ui/ash/ambient/photo_client.cc index 44c2aa3..d0d26970 100644 --- a/chrome/browser/ui/ash/ambient/photo_client.cc +++ b/chrome/browser/ui/ash/ambient/photo_client.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ui/ash/ambient/photo_client.h" +#include <vector> + +#include "base/callback.h" #include "build/buildflag.h" #include "chromeos/assistant/buildflags.h" @@ -21,5 +24,16 @@ } void PhotoClient::FetchTopicInfo(OnTopicInfoFetchedCallback callback) { - std::move(callback).Run(/*success=*/false, base::nullopt); + std::move(callback).Run(/*topic=*/base::nullopt); +} + +void PhotoClient::GetSettings( + ash::PhotoController::GetSettingsCallback callback) { + std::move(callback).Run(/*topic_source=*/base::nullopt); +} + +void PhotoClient::UpdateSettings( + int topic_source, + ash::PhotoController::UpdateSettingsCallback callback) { + std::move(callback).Run(/*success=*/false); }
diff --git a/chrome/browser/ui/ash/ambient/photo_client.h b/chrome/browser/ui/ash/ambient/photo_client.h index 79113d9..ea4406d0 100644 --- a/chrome/browser/ui/ash/ambient/photo_client.h +++ b/chrome/browser/ui/ash/ambient/photo_client.h
@@ -8,14 +8,13 @@ #include <memory> #include "ash/public/cpp/ambient/photo_controller.h" -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/optional.h" // The interface of a client to retrieve photos. class PhotoClient { public: using OnTopicInfoFetchedCallback = base::OnceCallback<void( - bool success, const base::Optional<ash::PhotoController::Topic>& topic)>; // Creates PhotoClient based on the build flag ENABLE_CROS_LIBASSISTANT. @@ -27,6 +26,12 @@ virtual ~PhotoClient() = default; virtual void FetchTopicInfo(OnTopicInfoFetchedCallback callback); + + virtual void GetSettings(ash::PhotoController::GetSettingsCallback callback); + + virtual void UpdateSettings( + int topic_source, + ash::PhotoController::UpdateSettingsCallback callback); }; #endif // CHROME_BROWSER_UI_ASH_AMBIENT_PHOTO_CLIENT_H_
diff --git a/chrome/browser/ui/ash/ambient/photo_controller_impl.cc b/chrome/browser/ui/ash/ambient/photo_controller_impl.cc index 54ad188..d3dd858b 100644 --- a/chrome/browser/ui/ash/ambient/photo_controller_impl.cc +++ b/chrome/browser/ui/ash/ambient/photo_controller_impl.cc
@@ -12,9 +12,8 @@ #include "components/account_id/account_id.h" #include "ui/gfx/image/image_skia.h" -PhotoControllerImpl::PhotoControllerImpl() : weak_factory_(this) { - photo_client_ = PhotoClient::Create(); -} +PhotoControllerImpl::PhotoControllerImpl() + : photo_client_(PhotoClient::Create()) {} PhotoControllerImpl::~PhotoControllerImpl() = default; @@ -24,11 +23,19 @@ weak_factory_.GetWeakPtr(), std::move(callback))); } +void PhotoControllerImpl::GetSettings(GetSettingsCallback callback) { + photo_client_->GetSettings(std::move(callback)); +} + +void PhotoControllerImpl::UpdateSettings(int topic_source, + UpdateSettingsCallback callback) { + photo_client_->UpdateSettings(topic_source, std::move(callback)); +} + void PhotoControllerImpl::OnNextImageInfoFetched( PhotoDownloadCallback callback, - bool success, const base::Optional<ash::PhotoController::Topic>& topic) { - if (!success || + if (!topic.has_value() || (topic->url.empty() && !topic->portrait_image_url.has_value())) { std::move(callback).Run(/*success=*/false, gfx::ImageSkia()); return; @@ -41,5 +48,5 @@ ->GetAccountId(); ash::AssistantImageDownloader::GetInstance()->Download( account_id, GURL(image_url), - base::BindOnce(std::move(callback), success)); + base::BindOnce(std::move(callback), /*success=*/true)); }
diff --git a/chrome/browser/ui/ash/ambient/photo_controller_impl.h b/chrome/browser/ui/ash/ambient/photo_controller_impl.h index c327f60f..e81e456 100644 --- a/chrome/browser/ui/ash/ambient/photo_controller_impl.h +++ b/chrome/browser/ui/ash/ambient/photo_controller_impl.h
@@ -24,16 +24,18 @@ // ash::PhotoController: void GetNextImage(PhotoDownloadCallback callback) override; + void GetSettings(GetSettingsCallback callback) override; + void UpdateSettings(int topic_source, + UpdateSettingsCallback callback) override; private: void OnNextImageInfoFetched( PhotoDownloadCallback callback, - bool success, const base::Optional<ash::PhotoController::Topic>& topic); std::unique_ptr<PhotoClient> photo_client_; - base::WeakPtrFactory<PhotoControllerImpl> weak_factory_; + base::WeakPtrFactory<PhotoControllerImpl> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(PhotoControllerImpl); };
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc index 3147572..7819b5ba 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/launch_utils.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/chromeos/apps/metrics/intent_handling_metrics.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/arc_web_contents_data.h" @@ -121,6 +120,7 @@ {ChromePage::PLUGINVMDETAILS, chrome::kPluginVmDetailsSubPage}, {ChromePage::PLUGINVMSHAREDPATHS, chrome::kPluginVmSharedPathsSubPage}, {ChromePage::OSACCESSIBILITY, chrome::kOsAccessibilitySubPage}, + {ChromePage::OSPRINTING, chrome::kOsPrintingSubPage}, {ChromePage::OSRESET, chrome::kOsResetSubPage}, {ChromePage::OSSEARCH, chrome::kOsSearchSubPage}, {ChromePage::POINTEROVERLAY, chrome::kPointerOverlaySubPage}, @@ -144,6 +144,7 @@ {ChromePage::PASSWORDS, chrome::kPasswordManagerSubPage}, {ChromePage::PRIVACY, chrome::kPrivacySubPage}, {ChromePage::RESET, chrome::kResetSubPage}, + {ChromePage::PRINTING, chrome::kPrintingSettingsSubPage}, {ChromePage::SEARCH, chrome::kSearchSubPage}, {ChromePage::SYNCSETUP, chrome::kSyncSetupSubPage}, {ChromePage::LANGUAGES, chrome::kLanguagesSubPage}, @@ -424,26 +425,24 @@ return; } - auto launch_container = apps::mojom::LaunchContainer::kLaunchContainerWindow; + int event_flags = apps::GetEventFlags( + apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_WINDOW, /*prefer_container=*/false); if (web_app::WebAppProviderBase::GetProviderBase(profile) ->registrar() .GetAppEffectiveDisplayMode(*app_id) == blink::mojom::DisplayMode::kBrowser) { - launch_container = apps::mojom::LaunchContainer::kLaunchContainerTab; + event_flags = apps::GetEventFlags( + apps::mojom::LaunchContainer::kLaunchContainerTab, + WindowOpenDisposition::NEW_FOREGROUND_TAB, /*prefer_container=*/false); } - apps::AppLaunchParams params = apps::AppLaunchParams( - *app_id, launch_container, WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceArc); - params.override_url = url; - content::WebContents* tab = - apps::LaunchService::Get(profile)->OpenApplication(params); - if (!tab) - return; - - // Add a flag to remember this tab originated in the ARC context. - tab->SetUserData(&arc::ArcWebContentsData::kArcTransitionFlag, - std::make_unique<arc::ArcWebContentsData>()); + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile); + DCHECK(proxy); + proxy->LaunchAppWithUrl(*app_id, event_flags, url, + apps::mojom::LaunchSource::kFromArc, + display::kInvalidDisplayId); } void ChromeNewWindowClient::OpenArcCustomTab(
diff --git a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc index dca10f87..3b80ffa 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
@@ -280,6 +280,8 @@ base_url.Resolve(chrome::kManageAccessibilitySubPage)); TestOpenChromePage(ChromePage::NETWORKSTYPEVPN, base_url.Resolve(chrome::kVPNSettingsSubPage)); + TestOpenChromePage(ChromePage::OSPRINTING, + base_url.Resolve(chrome::kOsPrintingSubPage)); TestOpenChromePage(ChromePage::POINTEROVERLAY, base_url.Resolve(chrome::kPointerOverlaySubPage)); TestOpenChromePage(ChromePage::OSRESET, @@ -363,6 +365,8 @@ base_url.Resolve(chrome::kPasswordManagerSubPage)); TestOpenChromePage(ChromePage::RESET, base_url.Resolve(chrome::kResetSubPage)); + TestOpenChromePage(ChromePage::PRINTING, + base_url.Resolve(chrome::kPrintingSettingsSubPage)); TestOpenChromePage(ChromePage::SEARCH, base_url.Resolve(chrome::kSearchSubPage)); TestOpenChromePage(ChromePage::SYNCSETUP,
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index bc29f2f6..f0a57fc 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -35,10 +35,11 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/app_service/launch_utils.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/speech_monitor.h" @@ -1525,10 +1526,12 @@ const Extension* extension = extension_registry()->GetExtensionById( last_loaded_extension_id(), extensions::ExtensionRegistry::ENABLED); EXPECT_TRUE(extension); - apps::LaunchService::Get(profile())->OpenApplication(apps::AppLaunchParams( - extension->id(), extensions::LaunchContainer::kLaunchContainerTab, - WindowOpenDisposition::NEW_WINDOW, - apps::mojom::AppLaunchSource::kSourceTest)); + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + extension->id(), extensions::LaunchContainer::kLaunchContainerTab, + WindowOpenDisposition::NEW_WINDOW, + apps::mojom::AppLaunchSource::kSourceTest)); EXPECT_EQ(++browsers, NumberOfDetectedLauncherBrowsers(false)); EXPECT_EQ(++tabs, NumberOfDetectedLauncherBrowsers(true));
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 9eb4169..a578db19 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -28,7 +28,9 @@ #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/defaults.h" @@ -1384,8 +1386,9 @@ // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. WebContents* app_window = - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension_app->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, WindowOpenDisposition::NEW_WINDOW, @@ -1556,8 +1559,9 @@ // Launch it in a window, as AppLauncherHandler::HandleLaunchApp() would. WebContents* app_window = - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension_app->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, WindowOpenDisposition::NEW_WINDOW,
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index d5561d7..b2b19044 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -16,7 +16,9 @@ #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" @@ -613,7 +615,9 @@ const apps::AppLaunchParams params = apps::AppLaunchParams( app_id, launch_container, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceKeyboard); - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); return; }
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index d17e500..39e1344 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -19,9 +19,10 @@ #include "base/system/sys_info.h" #include "build/branding_buildflags.h" #include "build/build_config.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/extensions/default_web_app_ids.h" @@ -154,7 +155,9 @@ profile, extension, 0, apps::mojom::AppLaunchSource::kSourceUntracked, -1); params.override_url = GURL(BuildQueryString(profile)); - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); return; } DVLOG(1) << "ReleaseNotes App Not Found";
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm index 76fa20a3..2d629f4b 100644 --- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm +++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -13,11 +13,13 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/apps/app_shim/app_shim_host_bootstrap_mac.h" #include "chrome/browser/apps/app_shim/app_shim_host_mac.h" #include "chrome/browser/apps/app_shim/app_shim_manager_mac.h" #include "chrome/browser/apps/app_shim/test/app_shim_listener_test_api_mac.h" -#include "chrome/browser/apps/launch_service/launch_service.h" #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -62,8 +64,9 @@ content::WindowedNotificationObserver app_loaded_observer( content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, content::NotificationService::AllSources()); - apps::LaunchService::Get(profile())->OpenApplication( - apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( app_->id(), apps::mojom::LaunchContainer::kLaunchContainerNone, WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/ui/extensions/app_launch_params.cc b/chrome/browser/ui/extensions/app_launch_params.cc index 05f76b3..ee3bfb5 100644 --- a/chrome/browser/ui/extensions/app_launch_params.cc +++ b/chrome/browser/ui/extensions/app_launch_params.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/extensions/app_launch_params.h" +#include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/profiles/profile.h" #include "extensions/browser/extension_prefs.h"
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc index 903c18b..84fa6e5 100644 --- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc +++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -17,6 +17,7 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/bind_test_util.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" @@ -38,8 +39,12 @@ #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h" #include "chrome/browser/ui/web_applications/web_app_menu_model.h" +#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/app_shortcut_manager.h" #include "chrome/browser/web_applications/components/external_install_options.h" +#include "chrome/browser/web_applications/components/install_manager.h" +#include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_id.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/test/web_app_install_observer.h" @@ -647,6 +652,36 @@ EvalJs(subframe, "document.body.innerText.trim();").ExtractString()); } +using BookmarkAppTest = HostedOrWebAppTest; + +IN_PROC_BROWSER_TEST_P(BookmarkAppTest, InstallFromSync) { + ASSERT_TRUE(https_server()->Start()); + + const GURL app_url = + https_server()->GetURL("/banners/manifest_test_page.html"); + const web_app::AppId app_id = web_app::GenerateAppIdFromURL(app_url); + + auto web_app_info = std::make_unique<WebApplicationInfo>(); + web_app_info->app_url = app_url; + web_app_info->scope = app_url.GetWithoutFilename(); + + base::RunLoop run_loop; + web_app::WebAppProviderBase* const provider = + web_app::WebAppProviderBase::GetProviderBase(profile()); + DCHECK(provider); + provider->install_manager().InstallBookmarkAppFromSync( + app_id, std::move(web_app_info), + base::BindLambdaForTesting([&](const web_app::AppId& installed_app_id, + web_app::InstallResultCode code) { + EXPECT_EQ(web_app::InstallResultCode::kSuccessNewInstall, code); + EXPECT_EQ(app_id, installed_app_id); + run_loop.Quit(); + })); + run_loop.Run(); + EXPECT_EQ(web_app::DisplayMode::kStandalone, + provider->registrar().GetAppDisplayMode(app_id)); +} + // Tests that platform apps can still load mixed content. IN_PROC_BROWSER_TEST_P(HostedAppTestWithAutoupgradesDisabled, MixedContentInPlatformApp) { @@ -1797,6 +1832,10 @@ ::testing::Values(AppType::HOSTED_APP)); INSTANTIATE_TEST_SUITE_P(All, + BookmarkAppTest, + ::testing::Values(AppType::BOOKMARK_APP)); + +INSTANTIATE_TEST_SUITE_P(All, HostedAppTestWithAutoupgradesDisabled, ::testing::Values(AppType::HOSTED_APP));
diff --git a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc index eba911014..a1c6b30 100644 --- a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc +++ b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc
@@ -6,7 +6,9 @@ #include "base/command_line.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -58,7 +60,9 @@ apps::mojom::AppLaunchSource::kSourceTest); content::WebContents* app_contents = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); CHECK(app_contents); return app_contents; }
diff --git a/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc b/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc index b77e519..f1a0bbb 100644 --- a/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc +++ b/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc
@@ -6,7 +6,9 @@ #include "base/macros.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" @@ -112,8 +114,9 @@ web_app::AppId settings_app_id = *web_app::GetAppIdForSystemWebApp( browser()->profile(), web_app::SystemAppType::SETTINGS); content::WebContents* contents = - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( settings_app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, WindowOpenDisposition::NEW_WINDOW,
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h index ceaa1a4..73e012f 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -91,6 +91,7 @@ mojo::PendingRemote<::viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) override; void OnStopped() override; + void OnLog(const std::string& /*message*/) override {} // Returns the dimensions of the multipurpose thumbnail that should be // captured from an entire webpage. Can be cropped or compressed later.
diff --git a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc index 6fd2207..93fe3d9 100644 --- a/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc +++ b/chrome/browser/ui/views/crostini/crostini_browser_test_util.cc
@@ -130,3 +130,32 @@ component_updater::CrOSComponentManager::Error::INSTALL_FAILURE, base::FilePath(), base::FilePath())); } + +class WebContentsWaiter : public content::WebContentsObserver { + public: + enum Operation { LOAD }; // Add other operations as required. + explicit WebContentsWaiter(content::WebContents* contents, + Operation operation) + : content::WebContentsObserver(contents), operation_(operation) {} + + ~WebContentsWaiter() override = default; + + void Wait() { run_loop_.Run(); } + + // content::WebContentsObserver: + void DidFinishLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url) override { + if (operation_ == LOAD) { + run_loop_.Quit(); + } + } + + private: + base::RunLoop run_loop_; + Operation operation_; +}; + +void CrostiniDialogBrowserTest::WaitForLoadFinished( + content::WebContents* contents) { + WebContentsWaiter(contents, WebContentsWaiter::LOAD).Wait(); +}
diff --git a/chrome/browser/ui/views/crostini/crostini_browser_test_util.h b/chrome/browser/ui/views/crostini/crostini_browser_test_util.h index 3958c91..468ac07 100644 --- a/chrome/browser/ui/views/crostini/crostini_browser_test_util.h +++ b/chrome/browser/ui/views/crostini/crostini_browser_test_util.h
@@ -15,6 +15,10 @@ class CrostiniBrowserTestChromeBrowserMainExtraParts; +namespace content { +class WebContents; +} + // Common base for Crostini dialog broswer tests. Allows tests to set network // connection type. class CrostiniDialogBrowserTest : public DialogBrowserTest { @@ -32,6 +36,8 @@ void UnregisterTermina(); + void WaitForLoadFinished(content::WebContents* contents); + protected: const bool register_termina_;
diff --git a/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc index 0d5e7f2..bd64705 100644 --- a/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc +++ b/chrome/browser/ui/views/crostini/crostini_update_component_view_browsertest.cc
@@ -24,25 +24,6 @@ #include "content/public/browser/web_contents_observer.h" #include "testing/gtest/include/gtest/gtest.h" -class LoadFinishedWaiter : public content::WebContentsObserver { - public: - explicit LoadFinishedWaiter(content::WebContents* contents) - : content::WebContentsObserver(contents) {} - - ~LoadFinishedWaiter() override = default; - - void Wait() { run_loop_.Run(); } - - // content::WebContentsObserver: - void DidFinishLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url) override { - run_loop_.Quit(); - } - - private: - base::RunLoop run_loop_; -}; - class CrostiniUpdateComponentViewBrowserTest : public CrostiniDialogBrowserTest { public: @@ -153,8 +134,8 @@ Browser* terminal_browser = web_app::FindSystemWebAppBrowser( browser()->profile(), web_app::SystemAppType::TERMINAL); CHECK_NE(nullptr, terminal_browser); - LoadFinishedWaiter(terminal_browser->tab_strip_model()->GetWebContentsAt(0)) - .Wait(); + WaitForLoadFinished( + terminal_browser->tab_strip_model()->GetWebContentsAt(0)); } ExpectView();
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc index b141fac..060033b 100644 --- a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc +++ b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
@@ -17,7 +17,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/win/scoped_propvariant.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/profiles/profile.h" @@ -199,8 +201,9 @@ LoadExtension(test_data_dir_.AppendASCII("app/")); EXPECT_TRUE(extension); - apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(apps::AppLaunchParams( + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( extension->id(), apps::mojom::LaunchContainer::kLaunchContainerWindow, WindowOpenDisposition::NEW_FOREGROUND_TAB, apps::mojom::AppLaunchSource::kSourceTest));
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 3ee576fab..af38122 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -133,6 +133,10 @@ OmniboxState::~OmniboxState() { } +enum OmniboxMenuCommands { + kShowUrl = views::Textfield::MenuCommands::kLastCommandId + 1, +}; + } // namespace // Animation chosen to match the default values in the edwardjung prototype. @@ -496,20 +500,13 @@ // In the base class, touch text selection is deactivated when a command is // executed. Since we are not always calling the base class implementation // here, we need to deactivate touch text selection here, too. - // - // Note: while it looks weird that some of these cases are IDC_* and some are - // IDS_*, that is intentional. The commands that do not have matching IDC_* - // constants are registered using their names' IDS constants as their command - // IDs. If at some point in the future someone adds a new IDC constant that - // clashes with one of these IDS constants, this stanza will fail to compile - // because there'll be a duplicate switch case. DestroyTouchSelection(); switch (command_id) { // These commands don't invoke the popup via OnBefore/AfterPossibleChange(). case IDC_PASTE_AND_GO: model()->PasteAndGo(GetClipboardText()); return; - case IDS_SHOW_URL: + case kShowUrl: model()->Unelide(true /* exit_query_in_omnibox */); return; case IDC_SHOW_FULL_URLS: @@ -525,7 +522,7 @@ return; // These commands do invoke the popup. - case IDS_APP_PASTE: + case Textfield::kPaste: ExecuteTextEditCommand(ui::TextEditCommand::PASTE); return; default: @@ -1454,13 +1451,13 @@ } bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const { - if (command_id == IDS_APP_PASTE) + if (command_id == Textfield::kPaste) return !GetReadOnly() && !GetClipboardText().empty(); if (command_id == IDC_PASTE_AND_GO) return !GetReadOnly() && model()->CanPasteAndGo(GetClipboardText()); // Menu item is only shown when it is valid. - if (command_id == IDS_SHOW_URL) + if (command_id == kShowUrl) return true; if (command_id == IDC_SHOW_FULL_URLS) return true; @@ -1837,7 +1834,7 @@ location_bar_view_->GetWebContents())) { send_tab_to_self::RecordSendTabToSelfClickResult( send_tab_to_self::kOmniboxMenu, SendTabToSelfClickResult::kShowItem); - int index = menu_contents->GetIndexOfCommandId(IDS_APP_UNDO); + int index = menu_contents->GetIndexOfCommandId(Textfield::kUndo); // Add a separator if this is not the first item. if (index) menu_contents->InsertSeparatorAt(index++, ui::NORMAL_SEPARATOR); @@ -1870,7 +1867,7 @@ menu_contents->InsertSeparatorAt(++index, ui::NORMAL_SEPARATOR); } - int paste_position = menu_contents->GetIndexOfCommandId(IDS_APP_PASTE); + int paste_position = menu_contents->GetIndexOfCommandId(Textfield::kPaste); DCHECK_GE(paste_position, 0); menu_contents->InsertItemWithStringIdAt(paste_position + 1, IDC_PASTE_AND_GO, IDS_PASTE_AND_GO); @@ -1884,15 +1881,12 @@ if (!GetReadOnly() && !model()->user_input_in_progress() && GetText() != controller()->GetLocationBarModel()->GetFormattedFullURL()) { - menu_contents->AddItemWithStringId(IDS_SHOW_URL, IDS_SHOW_URL); + menu_contents->AddItemWithStringId(kShowUrl, IDS_SHOW_URL); } } menu_contents->AddSeparator(ui::NORMAL_SEPARATOR); - // Minor note: We use IDC_ for command id here while the underlying textfield - // is using IDS_ for all its command ids. This is because views cannot depend - // on IDC_ for now. menu_contents->AddItemWithStringId(IDC_EDIT_SEARCH_ENGINES, IDS_EDIT_SEARCH_ENGINES);
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc index 39e34d09..e373445 100644 --- a/chrome/browser/ui/views/toolbar/reload_button.cc +++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -28,13 +28,6 @@ namespace { -// Contents of the Reload drop-down menu. -const int kReloadMenuItems[] = { - IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM, - IDS_RELOAD_MENU_HARD_RELOAD_ITEM, - IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM, -}; - const gfx::VectorIcon& GetIconForMode(ReloadButton::IconStyle icon_style, bool is_reload) { const bool touch_ui = ui::TouchUiController::Get()->touch_ui(); @@ -224,39 +217,21 @@ bool ReloadButton::GetAcceleratorForCommandId( int command_id, ui::Accelerator* accelerator) const { - switch (command_id) { - case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM: - GetWidget()->GetAccelerator(IDC_RELOAD, accelerator); - return true; - case IDS_RELOAD_MENU_HARD_RELOAD_ITEM: - GetWidget()->GetAccelerator(IDC_RELOAD_BYPASSING_CACHE, accelerator); - return true; - } return GetWidget()->GetAccelerator(command_id, accelerator); } void ReloadButton::ExecuteCommand(int command_id, int event_flags) { - int browser_command = 0; - switch (command_id) { - case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM: - browser_command = IDC_RELOAD; - break; - case IDS_RELOAD_MENU_HARD_RELOAD_ITEM: - browser_command = IDC_RELOAD_BYPASSING_CACHE; - break; - case IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM: - browser_command = IDC_RELOAD_CLEARING_CACHE; - break; - default: - NOTREACHED(); - } - ExecuteBrowserCommand(browser_command, event_flags); + ExecuteBrowserCommand(command_id, event_flags); } std::unique_ptr<ui::SimpleMenuModel> ReloadButton::CreateMenuModel() { auto menu_model = std::make_unique<ui::SimpleMenuModel>(this); - for (int item : kReloadMenuItems) - menu_model->AddItemWithStringId(item, item); + menu_model->AddItemWithStringId(IDC_RELOAD, + IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM); + menu_model->AddItemWithStringId(IDC_RELOAD_BYPASSING_CACHE, + IDS_RELOAD_MENU_HARD_RELOAD_ITEM); + menu_model->AddItemWithStringId(IDC_RELOAD_CLEARING_CACHE, + IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM); return menu_model; }
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc index 50af7567..c075fc24 100644 --- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc +++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -14,6 +14,7 @@ #include "base/optional.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator.h"
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc index 27d1d12..fc86418 100644 --- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc +++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -7,7 +7,9 @@ #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -59,10 +61,12 @@ Browser* LaunchWebAppBrowser(Profile* profile, const AppId& app_id) { EXPECT_TRUE( - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, - WindowOpenDisposition::CURRENT_TAB, - apps::mojom::AppLaunchSource::kSourceTest))); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::CURRENT_TAB, + apps::mojom::AppLaunchSource::kSourceTest))); Browser* browser = chrome::FindLastActive(); bool is_correct_app_browser = @@ -84,10 +88,12 @@ Browser* LaunchBrowserForWebAppInTab(Profile* profile, const AppId& app_id) { content::WebContents* web_contents = - apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( - app_id, apps::mojom::LaunchContainer::kLaunchContainerTab, - WindowOpenDisposition::NEW_FOREGROUND_TAB, - apps::mojom::AppLaunchSource::kSourceTest)); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(apps::AppLaunchParams( + app_id, apps::mojom::LaunchContainer::kLaunchContainerTab, + WindowOpenDisposition::NEW_FOREGROUND_TAB, + apps::mojom::AppLaunchSource::kSourceTest)); DCHECK(web_contents); WebAppTabHelperBase* tab_helper =
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc index 117d3170..24d01c0 100644 --- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/banners/test_app_banner_manager_desktop.h" #include "chrome/browser/extensions/browsertest_util.h" #include "chrome/browser/predictors/loading_predictor_config.h" @@ -134,7 +136,9 @@ WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest); content::WebContents* contents = - apps::LaunchService::Get(profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); url_observer.Wait(); return contents; }
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc index db77ce3..722ce6ca 100644 --- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -10,7 +10,9 @@ #include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/browser/web_applications/components/file_handler_manager.h" #include "chrome/browser/web_applications/components/web_app_prefs_utils.h" @@ -150,7 +152,9 @@ navigation_observer.StartWatchingNewWebContents(); content::WebContents* web_contents = - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); navigation_observer.Wait();
diff --git a/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc b/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc index 6177d719..61bcf03 100644 --- a/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc +++ b/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc
@@ -3,7 +3,9 @@ // found in the LICENSE file. #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/chromeos/extensions/default_web_app_ids.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/web_applications/system_web_app_manager.h" @@ -46,7 +48,9 @@ apps::mojom::AppLaunchSource::kSourceTest); content::WebContents* contents = - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); EXPECT_EQ(GURL(chrome::kChromeUIOSSettingsURL), contents->GetVisibleURL()); }
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc index e5848706..11110bd0 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
@@ -46,7 +46,11 @@ only_run_launch_closure_on_restart_(only_run_launch_closure_on_restart), launch_closure_{std::move(launch_closure)} {} -CrostiniUpgraderDialog::~CrostiniUpgraderDialog() = default; +CrostiniUpgraderDialog::~CrostiniUpgraderDialog() { + if (deletion_closure_for_testing_) { + std::move(deletion_closure_for_testing_).Run(); + } +} void CrostiniUpgraderDialog::GetDialogSize(gfx::Size* size) const { size->SetSize(::kDialogWidth, ::kDialogHeight); @@ -65,10 +69,19 @@ params->z_order = ui::ZOrderLevel::kNormal; } +void CrostiniUpgraderDialog::SetDeletionClosureForTesting( + base::OnceClosure deletion_closure_for_testing) { + deletion_closure_for_testing_ = std::move(deletion_closure_for_testing); +} + bool CrostiniUpgraderDialog::CanCloseDialog() const { // TODO(929571): If other WebUI Dialogs also need to let the WebUI control // closing logic, we should find a more general solution. + if (deletion_closure_for_testing_) { + // Running in a test. + return true; + } // Disallow closing without WebUI consent. return upgrader_ui_ == nullptr || upgrader_ui_->can_close(); }
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h index dc94be2..7f1a219 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
@@ -22,6 +22,9 @@ static void Show(base::OnceClosure launch_closure, bool only_run_launch_closure_on_restart = false); + void SetDeletionClosureForTesting( + base::OnceClosure deletion_closure_for_testing); + private: explicit CrostiniUpgraderDialog(base::OnceClosure launch_closure, bool only_run_launch_closure_on_restart); @@ -37,10 +40,10 @@ void OnCloseContents(content::WebContents* source, bool* out_close_dialog) override; - private: CrostiniUpgraderUI* upgrader_ui_ = nullptr; // Not owned. const bool only_run_launch_closure_on_restart_; base::OnceClosure launch_closure_; + base::OnceClosure deletion_closure_for_testing_; }; } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc new file mode 100644 index 0000000..d106d06 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc
@@ -0,0 +1,136 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h" + +#include "base/feature_list.h" +#include "base/metrics/histogram_base.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "chrome/browser/chromeos/crostini/crostini_manager.h" +#include "chrome/browser/chromeos/crostini/crostini_test_helper.h" +#include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h" +#include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/crostini/crostini_browser_test_util.h" +#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom.h" +#include "chrome/common/webui_url_constants.h" +#include "chromeos/dbus/cicerone/cicerone_service.pb.h" +#include "content/public/browser/web_ui.h" +#include "testing/gtest/include/gtest/gtest.h" + +constexpr char kDesktopFileId[] = "test_app"; +constexpr int kDisplayId = 0; + +class CrostiniUpgraderDialogBrowserTest : public CrostiniDialogBrowserTest { + public: + CrostiniUpgraderDialogBrowserTest() + : CrostiniDialogBrowserTest(true /*register_termina*/), + app_id_(crostini::CrostiniTestHelper::GenerateAppId(kDesktopFileId)) {} + + // DialogBrowserTest: + void ShowUi(const std::string& name) override { + chromeos::CrostiniUpgraderDialog::Show(base::DoNothing(), false); + } + + chromeos::CrostiniUpgraderDialog* GetCrostiniUpgraderDialog() { + auto url = GURL{chrome::kChromeUICrostiniUpgraderUrl}; + return reinterpret_cast<chromeos::CrostiniUpgraderDialog*>( + chromeos::SystemWebDialogDelegate::FindInstance(url.spec())); + } + + void SafelyCloseDialog() { + auto* upgrader_dialog = GetCrostiniUpgraderDialog(); + + // Make sure the WebUI has launches sufficiently. Closing immediately would + // miss breakages in the underlying plumbing. + auto* web_contents = upgrader_dialog->GetWebUIForTest()->GetWebContents(); + WaitForLoadFinished(web_contents); + + // Now there should be enough WebUI hooked up to close properly. + base::RunLoop run_loop; + upgrader_dialog->SetDeletionClosureForTesting(run_loop.QuitClosure()); + upgrader_dialog->Close(); + run_loop.Run(); + } + + void ExpectDialog() { + // A new Widget was created in ShowUi() or since the last VerifyUi(). + EXPECT_TRUE(crostini_manager()->GetCrostiniDialogStatus( + crostini::DialogType::UPGRADER)); + + EXPECT_NE(nullptr, GetCrostiniUpgraderDialog()); + } + + void ExpectNoDialog() { + // No new Widget was created in ShowUi() or since the last VerifyUi(). + EXPECT_FALSE(crostini_manager()->GetCrostiniDialogStatus( + crostini::DialogType::UPGRADER)); + // Our dialog has really been deleted. + EXPECT_EQ(nullptr, GetCrostiniUpgraderDialog()); + } + + void RegisterApp() { + vm_tools::apps::ApplicationList app_list = + crostini::CrostiniTestHelper::BasicAppList( + kDesktopFileId, crostini::kCrostiniDefaultVmName, + crostini::kCrostiniDefaultContainerName); + guest_os::GuestOsRegistryServiceFactory::GetForProfile(browser()->profile()) + ->UpdateApplicationList(app_list); + } + + void DowngradeOSRelease() { + vm_tools::cicerone::OsRelease os_release; + os_release.set_id("debian"); + os_release.set_version_id("9"); + auto container_id = crostini::DefaultContainerId(); + crostini_manager()->SetContainerOsRelease( + container_id.vm_name, container_id.container_name, os_release); + } + + const std::string& app_id() const { return app_id_; } + + crostini::CrostiniManager* crostini_manager() { + return crostini::CrostiniManager::GetForProfile(browser()->profile()); + } + + private: + std::string app_id_; + + DISALLOW_COPY_AND_ASSIGN(CrostiniUpgraderDialogBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(CrostiniUpgraderDialogBrowserTest, + NoDialogOnNormalStartup) { + base::HistogramTester histogram_tester; + RegisterApp(); + + crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId); + ExpectNoDialog(); +} + +IN_PROC_BROWSER_TEST_F(CrostiniUpgraderDialogBrowserTest, ShowsOnAppLaunch) { + base::HistogramTester histogram_tester; + + DowngradeOSRelease(); + RegisterApp(); + + crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId); + ExpectDialog(); + + SafelyCloseDialog(); + ExpectNoDialog(); + + // Once only - second time we launch an app, the dialog should not appear. + crostini::LaunchCrostiniApp(browser()->profile(), app_id(), kDisplayId); + ExpectNoDialog(); + + histogram_tester.ExpectUniqueSample( + crostini::kUpgradeDialogEventHistogram, + static_cast<base::HistogramBase::Sample>( + crostini::UpgradeDialogEvent::kDialogShown), + 1); +}
diff --git a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc index 40c86e9..8dd97791 100644 --- a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc
@@ -52,8 +52,10 @@ DemoSetupController::DemoSetupError::RecoveryMethod::kPowerwash); } -void DemoSetupScreenHandler::IncrementSetupProgress(bool complete) { - CallJS("login.DemoSetupScreen.incrementSetupProgress", complete); +void DemoSetupScreenHandler::SetCurrentSetupStep( + DemoSetupController::DemoSetupStep current_step) { + CallJS("login.DemoSetupScreen.setCurrentSetupStep", + DemoSetupController::GetDemoSetupStepString(current_step)); } void DemoSetupScreenHandler::OnSetupSucceeded() { @@ -72,13 +74,21 @@ IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL); builder->Add("demoSetupErrorScreenPowerwashButtonLabel", IDS_LOCAL_STATE_ERROR_POWERWASH_BUTTON); + + builder->Add("demoSetupProgressStepDownload", + IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD); + builder->Add("demoSetupProgressStepEnroll", + IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL); } void DemoSetupScreenHandler::GetAdditionalParameters( base::DictionaryValue* parameters) { parameters->SetBoolKey( - "showProgressBarInDemoModeSetup", - base::FeatureList::IsEnabled(features::kShowProgressBarInDemoModeSetup)); + "showStepsInDemoModeSetup", + base::FeatureList::IsEnabled(features::kShowStepsInDemoModeSetup)); + + parameters->SetPath("demoSetupSteps", + DemoSetupController::GetDemoSetupSteps()); } } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h index 732b33d6..e21cadb 100644 --- a/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
@@ -28,8 +28,9 @@ // Sets view and screen. virtual void Bind(DemoSetupScreen* screen) = 0; - // Increments setup progress percentage for UI. - virtual void IncrementSetupProgress(bool complete) = 0; + // Updates current setup step. + virtual void SetCurrentSetupStep( + DemoSetupController::DemoSetupStep current_step) = 0; // Handles successful setup. virtual void OnSetupSucceeded() = 0; @@ -53,7 +54,8 @@ void Show() override; void Hide() override; void Bind(DemoSetupScreen* screen) override; - void IncrementSetupProgress(bool complete) override; + void SetCurrentSetupStep( + DemoSetupController::DemoSetupStep current_step) override; void OnSetupFailed(const DemoSetupController::DemoSetupError& error) override; void OnSetupSucceeded() override;
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index 93cb95d..d2c6d2ab 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -20,7 +20,10 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_launch_params.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/crx_installer.h" @@ -535,7 +538,9 @@ : apps::mojom::LaunchContainer::kLaunchContainerTab, disposition, apps::mojom::AppLaunchSource::kSourceNewTabPage); params.override_url = override_url; - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); } else { // To give a more "launchy" experience when using the NTP launcher, we close // it automatically. @@ -552,7 +557,9 @@ extensions::AppLaunchSource::kSourceNewTabPage); params.override_url = override_url; WebContents* new_contents = - apps::LaunchService::Get(profile)->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(profile) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); // This will also destroy the handler, so do not perform any actions after. if (new_contents != old_contents && browser &&
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc index d9796ed..c7abe54 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
@@ -31,6 +31,8 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/supervised_user/supervised_user_service.h" +#include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h" #include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h" #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h" @@ -796,8 +798,12 @@ {"pluginVmRemoveButton", IDS_SETTINGS_PLUGIN_VM_REMOVE_BUTTON}, {"pluginVmRemoveConfirmationDialogMessage", IDS_SETTINGS_PLUGIN_VM_CONFIRM_REMOVE_DIALOG_BODY}, + {"pluginVmCameraAccessTitle", IDS_SETTINGS_PLUGIN_VM_CAMERA_ACCESS_TITLE}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); + html_source->AddBoolean("showPluginVmCamera", + base::FeatureList::IsEnabled( + chromeos::features::kPluginVmShowCameraSetting)); } void AddAndroidAppStrings(content::WebUIDataSource* html_source) { @@ -857,7 +863,8 @@ AddLocalizedStringsBulk(html_source, kLocalizedStrings); } -void AddParentalControlStrings(content::WebUIDataSource* html_source) { +void AddParentalControlStrings(content::WebUIDataSource* html_source, + Profile* profile) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"parentalControlsPageTitle", IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_TITLE}, {"parentalControlsPageSetUpLabel", @@ -875,6 +882,27 @@ html_source->AddBoolean( "isChild", user_manager::UserManager::Get()->IsLoggedInAsChildUser()); + + if (user_manager::UserManager::Get()->IsLoggedInAsChildUser()) { + SupervisedUserService* supervised_user_service = + SupervisedUserServiceFactory::GetForProfile(profile); + std::string custodian = supervised_user_service->GetCustodianName(); + std::string second_custodian = + supervised_user_service->GetSecondCustodianName(); + + base::string16 child_managed_tooltip; + if (second_custodian.empty()) { + child_managed_tooltip = l10n_util::GetStringFUTF16( + IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP, + base::UTF8ToUTF16(custodian)); + } else { + child_managed_tooltip = l10n_util::GetStringFUTF16( + IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP, + base::UTF8ToUTF16(custodian), base::UTF8ToUTF16(second_custodian)); + } + html_source->AddString("accountManagerPrimaryAccountChildManagedTooltip", + child_managed_tooltip); + } } void AddBluetoothStrings(content::WebUIDataSource* html_source) { @@ -2047,7 +2075,7 @@ AddGoogleAssistantStrings(html_source, profile); AddLanguagesStrings(html_source); AddMultideviceStrings(html_source); - AddParentalControlStrings(html_source); + AddParentalControlStrings(html_source, profile); AddPageVisibilityStrings(html_source); AddPeoplePageStrings(html_source, profile); AddPersonalizationStrings(html_source);
diff --git a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc index b0449d5f..b2d26069 100644 --- a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc +++ b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
@@ -643,6 +643,8 @@ url_loader().SetNextLoadUrlResult( GURL("about:blank"), web_app::WebAppUrlLoader::Result::kUrlLoaded); + url_loader().SetNextLoadUrlResult( + AppUrl(), web_app::WebAppUrlLoader::Result::kRedirectedUrlLoaded); { base::RunLoop run_loop;
diff --git a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc index 53cf771..6ff16f0 100644 --- a/chrome/browser/web_applications/system_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/system_web_app_manager_browsertest.cc
@@ -10,13 +10,15 @@ #include <vector> #include "base/bind.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/path_service.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/native_file_system/native_file_system_permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" @@ -26,6 +28,7 @@ #include "chrome/browser/web_applications/test/test_web_app_provider.h" #include "chrome/browser/web_applications/web_app_tab_helper.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/webui_url_constants.h" #include "chrome/services/app_service/public/cpp/app_registry_cache.h" #include "chrome/services/app_service/public/cpp/app_update.h" @@ -120,11 +123,9 @@ content::WebContents* SystemWebAppManagerBrowserTestBase::LaunchApp( const apps::AppLaunchParams& params) { - // Use apps::LaunchService::OpenApplication() to get the most coverage. E.g., - // this is what is invoked by file_manager::file_tasks::ExecuteWebTask() on - // ChromeOS. - return apps::LaunchService::Get(browser()->profile()) - ->OpenApplication(params); + return apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); } SystemWebAppManagerBrowserTest::SystemWebAppManagerBrowserTest( @@ -272,7 +273,9 @@ content::TestNavigationObserver navigation_observer(launch_url); navigation_observer.StartWatchingNewWebContents(); content::WebContents* web_contents = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); navigation_observer.Wait(); // Set up a Promise that resolves to launchParams, when launchQueue's consumer @@ -309,7 +312,9 @@ &temp_file_path2)); params.launch_files = {temp_file_path2}; content::WebContents* web_contents2 = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); // WebContents* should be the same because we are passing launchParams to the // opened application. @@ -331,6 +336,165 @@ SystemWebAppManagerLaunchDirectoryBrowserTest() : SystemWebAppManagerFileHandlingBrowserTestBase( IncludeLaunchDirectory::kYes) {} + + // Returns the content of |jsIdentifier| file handle. + std::string ReadContentFromJsFileHandle(content::WebContents* web_contents, + const std::string& jsIdentifier) { + std::string js_file_content; + EXPECT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, + "Promise.resolve(" + jsIdentifier + ")" + + ".then(async (identifier) => {" + " const file = await identifier.getFile();" + " const content = await file.text();" + " window.domAutomationController.send(content);" + "});", + &js_file_content)); + return js_file_content; + } + + // Writes |contentToWrite| to |jsIdentifier| file handle. Returns whether + // JavaScript execution finishes. + bool WriteContentToJsFileHandle(content::WebContents* web_contents, + const std::string& jsIdentifier, + const std::string& contentToWrite) { + bool file_written; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + web_contents, + content::JsReplace( + "Promise.resolve(" + jsIdentifier + ")" + + ".then(async (file_handle) => {" + " const writable = await file_handle.createWritable();" + " await writable.write($1);" + " await writable.close();" + " window.domAutomationController.send(true);" + "});", + contentToWrite), + &file_written)); + return file_written; + } + + // Remove file by |file_name| from |jsIdentifier| directory handle. Returns + // whether JavaScript execution finishes. + bool RemoveFileFromJsDirectoryHandle(content::WebContents* web_contents, + const std::string& jsIdentifier, + const std::string& file_name) { + bool file_removed; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + web_contents, + content::JsReplace("Promise.resolve(" + jsIdentifier + ")" + + ".then(async (dir_handle) => {" + " await dir_handle.removeEntry($1);" + " domAutomationController.send(true);" + "});", + file_name), + &file_removed)); + return file_removed; + } + + std::string ReadFileContent(const base::FilePath& path) { + std::string content; + EXPECT_TRUE(base::ReadFileToString(path, &content)); + return content; + } + + // Launch the App with |base_dir| and a file inside this directory, then test + // SWA can 1) read and write to the launch file; 2) read and write to other + // files inside the launch directory; 3) read and write to the launch + // directory (i.e. list and delete files). + void TestPermissionsForLaunchDirectory(const base::FilePath& base_dir) { + apps::AppLaunchParams params = LaunchParamsForApp(GetMockAppType()); + params.source = apps::mojom::AppLaunchSource::kSourceChromeInternal; + + base::ScopedAllowBlockingForTesting allow_blocking; + + // Create the launch file, which stores 4 characters "test". + base::FilePath launch_file_path; + ASSERT_TRUE(base::CreateTemporaryFileInDir(base_dir, &launch_file_path)); + ASSERT_EQ(4, base::WriteFile(launch_file_path, "test", 4)); + + // Launch the App. + const GURL& launch_url = WebAppProvider::Get(browser()->profile()) + ->registrar() + .GetAppLaunchURL(params.app_id); + params.launch_files = {launch_file_path}; + content::TestNavigationObserver navigation_observer(launch_url); + navigation_observer.StartWatchingNewWebContents(); + content::WebContents* web_contents = + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); + navigation_observer.Wait(); + + // Launch directories and files passed to system web apps should + // automatically be granted write permission. Users should not get + // permission prompts. So we auto deny them (if they show up). + NativeFileSystemPermissionRequestManager::FromWebContents(web_contents) + ->set_auto_response_for_test(permissions::PermissionAction::DENIED); + + // Set up a Promise to resolves to launchParams, when launchQueue's consumer + // callback is called. + EXPECT_TRUE(content::ExecuteScript( + web_contents, + "window.launchParamsPromise = new Promise(resolve => {" + " window.resolveLaunchParamsPromise = resolve;" + "});" + "launchQueue.setConsumer(launchParams => {" + " window.resolveLaunchParamsPromise(launchParams);" + "});")); + + // Wait for launch. Set window.launchParams for manipulation. + EXPECT_TRUE(content::ExecuteScript( + web_contents, + "window.launchParamsPromise.then(launchParams => {" + " window.launchParams = launchParams;" + "});")); + + // Check we can read and write to the launch file. + std::string launch_file_js_handle = "window.launchParams.files[1]"; + EXPECT_EQ("test", + ReadContentFromJsFileHandle(web_contents, launch_file_js_handle)); + EXPECT_TRUE(WriteContentToJsFileHandle(web_contents, launch_file_js_handle, + "js_written")); + EXPECT_EQ("js_written", ReadFileContent(launch_file_path)); + + // Check we can read and write to a different file inside the directory. + // Note, this also checks we can read the launch directory, using + // directory_handle.getFile(). + base::FilePath non_launch_file_path; + ASSERT_TRUE( + base::CreateTemporaryFileInDir(base_dir, &non_launch_file_path)); + ASSERT_EQ(5, base::WriteFile(non_launch_file_path, "test2", 5)); + + std::string non_launch_file_js_handle = + content::JsReplace("window.launchParams.files[0].getFile($1)", + non_launch_file_path.BaseName().AsUTF8Unsafe()); + EXPECT_EQ("test2", ReadContentFromJsFileHandle(web_contents, + non_launch_file_js_handle)); + EXPECT_TRUE(WriteContentToJsFileHandle( + web_contents, non_launch_file_js_handle, "js_written2")); + EXPECT_EQ("js_written2", ReadFileContent(non_launch_file_path)); + + // Check the launch file can be deleted. + std::string launch_dir_js_handle = "window.launchParams.files[0]"; + EXPECT_TRUE(RemoveFileFromJsDirectoryHandle( + web_contents, launch_dir_js_handle, + launch_file_path.BaseName().AsUTF8Unsafe())); + EXPECT_FALSE(base::PathExists(launch_file_path)); + + // Check the non-launch file can be deleted. + EXPECT_TRUE(RemoveFileFromJsDirectoryHandle( + web_contents, launch_dir_js_handle, + non_launch_file_path.BaseName().AsUTF8Unsafe())); + EXPECT_FALSE(base::PathExists(non_launch_file_path)); + + // Check a file can be created. + std::string new_file_js_handle = content::JsReplace( + "window.launchParams.files[0].getFile($1, {create:true})", "new_file"); + EXPECT_TRUE(WriteContentToJsFileHandle(web_contents, new_file_js_handle, + "js_new_file")); + EXPECT_EQ("js_new_file", ReadFileContent(base_dir.AppendASCII("new_file"))); + } }; // Launching behavior for apps that do not want to received launch directory are @@ -359,7 +523,9 @@ content::TestNavigationObserver navigation_observer(launch_url); navigation_observer.StartWatchingNewWebContents(); content::WebContents* web_contents = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); navigation_observer.Wait(); // Set up a Promise that resolves to launchParams, when launchQueue's consumer @@ -423,7 +589,9 @@ &temp_file_path2)); params.launch_files = {temp_file_path2}; content::WebContents* web_contents2 = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); // WebContents* should be the same because we are passing launchParams to the // opened application. @@ -462,45 +630,33 @@ "domAutomationController.send(window.secondLaunchParams.files[1].name)", &file_name)); EXPECT_EQ(temp_file_path2.BaseName().AsUTF8Unsafe(), file_name); +} - // Launch directories and files passed to system web apps should automatically - // be granted write permission. Users should not get permission prompts. Here - // we execute some JavaScript code that modifies and deletes files in the - // directory. +IN_PROC_BROWSER_TEST_P(SystemWebAppManagerLaunchDirectoryBrowserTest, + ReadWritePermissions_OrdinaryDirectory) { + WaitForTestSystemAppInstall(); - // Auto deny prompts (if they show up). - NativeFileSystemPermissionRequestManager::FromWebContents(web_contents) - ->set_auto_response_for_test(permissions::PermissionAction::DENIED); + // Test for ordinary directory. + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_directory; + ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); + TestPermissionsForLaunchDirectory(temp_directory.GetPath()); +} - // Modifies the launch file. Reuse the first launch directory. - bool writer_closed; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - web_contents, - "window.firstLaunchParams.files[1].createWritable().then(" - " async writer => {" - " console.log(writer);" - " await writer.write('test');" - " await writer.close();" - " domAutomationController.send(true);" - " }" - ");", - &writer_closed)); - EXPECT_TRUE(writer_closed); +IN_PROC_BROWSER_TEST_P(SystemWebAppManagerLaunchDirectoryBrowserTest, + ReadWritePermissions_SensitiveDirectory) { + WaitForTestSystemAppInstall(); - std::string read_contents; - EXPECT_TRUE(base::ReadFileToString(temp_file_path, &read_contents)); - EXPECT_EQ("test", read_contents); - - // Deletes the launch file. Reuse the second launch directory. - bool file_removed; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - web_contents, - "window.secondLaunchParams.files[0].removeEntry(" - " window.secondLaunchParams.files[1].name" - ").then(_ => domAutomationController.send(true));", - &file_removed)); - EXPECT_TRUE(file_removed); - EXPECT_FALSE(base::PathExists(temp_file_path2)); + // Test for sensitive directory (which are otherwise blocked by + // NativeFileSystem API). It is safe to use |chrome::DIR_DEFAULT_DOWNLOADS|, + // because InProcBrowserTest fixture sets up different download directory for + // each test cases. + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath sensitive_dir; + ASSERT_TRUE( + base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &sensitive_dir)); + ASSERT_TRUE(base::DirectoryExists(sensitive_dir)); + TestPermissionsForLaunchDirectory(sensitive_dir); } class SystemWebAppManagerFileHandlingOriginTrialsBrowserTest @@ -541,7 +697,9 @@ content::TestNavigationObserver navigation_observer(launch_url); navigation_observer.StartWatchingNewWebContents(); content::WebContents* web_contents = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); navigation_observer.Wait(); // Wait for the Promise to resolve.
diff --git a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc index 941a799f..c8f9b4b9 100644 --- a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc +++ b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
@@ -6,7 +6,9 @@ #include "base/test/bind_test_util.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" @@ -100,7 +102,9 @@ WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest); content::WebContents* contents = - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); controller = chrome::FindBrowserWithWebContents(contents) ->app_controller() ->AsWebAppBrowserController();
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc index a5e39f8..3b46395 100644 --- a/chrome/browser/web_applications/web_app_install_manager.cc +++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -147,10 +147,10 @@ finalizer(), data_retriever_factory_.Run()); base::OnceClosure start_task = base::BindOnce( - &WebAppInstallTask::InstallWebAppFromInfoRetrieveIcons, + &WebAppInstallTask::LoadAndInstallWebAppFromSync, base::Unretained(task.get()), EnsureWebContentsCreated(), - std::move(web_application_info), is_locally_installed, - WebappInstallSource::SYNC, + base::Unretained(url_loader_.get()), std::move(web_application_info), + is_locally_installed, WebappInstallSource::SYNC, base::BindOnce(&WebAppInstallManager::OnQueuedTaskCompleted, base::Unretained(this), task.get(), std::move(callback)));
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index 6f895358..303073f 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -228,8 +228,9 @@ base::Unretained(this), /*force_shortcut_app=*/false)); } -void WebAppInstallTask::InstallWebAppFromInfoRetrieveIcons( +void WebAppInstallTask::LoadAndInstallWebAppFromSync( content::WebContents* web_contents, + WebAppUrlLoader* url_loader, std::unique_ptr<WebApplicationInfo> web_application_info, bool is_locally_installed, WebappInstallSource install_source, @@ -241,18 +242,17 @@ install_source_ = install_source; background_installation_ = true; - std::vector<GURL> icon_urls = - GetValidIconUrlsToDownload(*web_application_info); + // Default display mode, used if we fail to load the manifest. + web_application_info->display_mode = DisplayMode::kBrowser; - // Skip downloading the page favicons as everything in is the URL list. - data_retriever_->GetIcons( - web_contents, icon_urls, /*skip_page_fav_icons*/ true, - install_source_ == WebappInstallSource::SYNC - ? WebAppIconDownloader::Histogram::kForSync - : WebAppIconDownloader::Histogram::kForCreate, - base::BindOnce(&WebAppInstallTask::OnIconsRetrieved, - base::Unretained(this), std::move(web_application_info), - is_locally_installed)); + const GURL launch_url = web_application_info->app_url; + url_loader->LoadUrl( + launch_url, web_contents, + WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef, + base::BindOnce( + &WebAppInstallTask::OnWebAppFromSyncUrlLoadedRetrieveManifest, + weak_ptr_factory_.GetWeakPtr(), std::move(web_application_info), + is_locally_installed)); } void WebAppInstallTask::UpdateWebAppFromInfo( @@ -616,6 +616,59 @@ for_installable_site)); } +void WebAppInstallTask::OnWebAppFromSyncUrlLoadedRetrieveManifest( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed, + WebAppUrlLoader::Result result) { + if (ShouldStopInstall()) + return; + + if (result != WebAppUrlLoader::Result::kUrlLoaded) { + WebAppFromSyncLoadIcons(std::move(web_application_info), + is_locally_installed); + return; + } + + web_contents()->GetManifest( + base::BindOnce(&WebAppInstallTask::OnWebAppFromSyncManifestRetrieved, + weak_ptr_factory_.GetWeakPtr(), + std::move(web_application_info), is_locally_installed)); +} + +void WebAppInstallTask::OnWebAppFromSyncManifestRetrieved( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed, + const GURL& manifest_url, + const blink::Manifest& manifest) { + if (ShouldStopInstall()) + return; + + if (!manifest.IsEmpty()) { + // TODO(crbug.com/1067519): Copy more fields from the manifest. + web_application_info->display_mode = manifest.display; + } + + WebAppFromSyncLoadIcons(std::move(web_application_info), + is_locally_installed); +} + +void WebAppInstallTask::WebAppFromSyncLoadIcons( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed) { + std::vector<GURL> icon_urls = + GetValidIconUrlsToDownload(*web_application_info); + + // Skip downloading the page favicons as everything in is the URL list. + data_retriever_->GetIcons( + web_contents(), icon_urls, /*skip_page_fav_icons*/ true, + install_source_ == WebappInstallSource::SYNC + ? WebAppIconDownloader::Histogram::kForSync + : WebAppIconDownloader::Histogram::kForCreate, + base::BindOnce(&WebAppInstallTask::OnIconsRetrieved, + base::Unretained(this), std::move(web_application_info), + is_locally_installed)); +} + void WebAppInstallTask::OnIconsRetrieved( std::unique_ptr<WebApplicationInfo> web_app_info, bool is_locally_installed,
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h index 7d48f61..f3ce279 100644 --- a/chrome/browser/web_applications/web_app_install_task.h +++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -118,10 +118,13 @@ InstallManager::OnceInstallCallback callback); // Starts background installation of a web app: does not show UI dialog. - // |web_application_info| contains all the data needed for installation. Icons - // will be downloaded from the icon URLs provided in |web_application_info|. - void InstallWebAppFromInfoRetrieveIcons( + // |web_application_info| contains most of the data needed for installation. + // The launch URL and its manifest are loaded to determine the display mode. + // Icons will be downloaded from the icon URLs provided in + // |web_application_info|. Doesn't memorize |url_loader| pointer. + void LoadAndInstallWebAppFromSync( content::WebContents* web_contents, + WebAppUrlLoader* url_loader, std::unique_ptr<WebApplicationInfo> web_application_info, bool is_locally_installed, WebappInstallSource install_source, @@ -204,6 +207,19 @@ const std::string& intent, bool should_intent_to_store); + void OnWebAppFromSyncUrlLoadedRetrieveManifest( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed, + WebAppUrlLoader::Result result); + void OnWebAppFromSyncManifestRetrieved( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed, + const GURL& manifest_url, + const blink::Manifest& manifest); + void WebAppFromSyncLoadIcons( + std::unique_ptr<WebApplicationInfo> web_application_info, + bool is_locally_installed); + void OnIconsRetrieved(std::unique_ptr<WebApplicationInfo> web_app_info, bool is_locally_installed, IconsMap icons_map);
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc index 4fdeb2ea..0cb08280 100644 --- a/chrome/browser/web_applications/web_app_install_task_unittest.cc +++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -333,16 +333,16 @@ return app_id; } - AppId InstallWebAppFromInfoRetrieveIcons(const GURL& url, - bool is_locally_installed) { + AppId LoadAndInstallWebAppFromSync(const GURL& url, + bool is_locally_installed) { AppId app_id; auto web_app_info = std::make_unique<WebApplicationInfo>(); web_app_info->app_url = url; base::RunLoop run_loop; - install_task_->InstallWebAppFromInfoRetrieveIcons( - web_contents(), std::move(web_app_info), is_locally_installed, - WebappInstallSource::SYNC, + install_task_->LoadAndInstallWebAppFromSync( + web_contents(), &url_loader(), std::move(web_app_info), + is_locally_installed, WebappInstallSource::SYNC, base::BindLambdaForTesting( [&](const AppId& installed_app_id, InstallResultCode code) { ASSERT_EQ(InstallResultCode::kSuccessNewInstall, code); @@ -908,12 +908,14 @@ run_loop.Run(); } -TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfoRetrieveIcons_TwoIcons) { +TEST_F(WebAppInstallTaskTest, LoadAndInstallWebAppFromSync_TwoIcons) { SetInstallFinalizerForTesting(); const GURL url{"https://example.com/path"}; const GURL icon1_url{"https://example.com/path/icon1.png"}; const GURL icon2_url{"https://example.com/path/icon2.png"}; + url_loader().SetNextLoadUrlResult( + url, WebAppUrlLoader::Result::kRedirectedUrlLoaded); CreateDefaultDataToRetrieve(url); @@ -940,9 +942,9 @@ base::RunLoop run_loop; - install_task_->InstallWebAppFromInfoRetrieveIcons( - web_contents(), std::move(web_app_info), /*is_locally_installed=*/true, - WebappInstallSource::SYNC, + install_task_->LoadAndInstallWebAppFromSync( + web_contents(), &url_loader(), std::move(web_app_info), + /*is_locally_installed=*/true, WebappInstallSource::SYNC, base::BindLambdaForTesting( [&](const AppId& installed_app_id, InstallResultCode code) { EXPECT_EQ(InstallResultCode::kSuccessNewInstall, code); @@ -978,10 +980,12 @@ run_loop.Run(); } -TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfoRetrieveIcons_NoIcons) { +TEST_F(WebAppInstallTaskTest, LoadAndInstallWebAppFromSync_NoIcons) { SetInstallFinalizerForTesting(); const GURL url{"https://example.com/path"}; + url_loader().SetNextLoadUrlResult( + url, WebAppUrlLoader::Result::kRedirectedUrlLoaded); CreateDefaultDataToRetrieve(url); const AppId app_id = GenerateAppIdFromURL(url); @@ -992,9 +996,9 @@ base::RunLoop run_loop; - install_task_->InstallWebAppFromInfoRetrieveIcons( - web_contents(), std::move(web_app_info), /*is_locally_installed=*/false, - WebappInstallSource::SYNC, + install_task_->LoadAndInstallWebAppFromSync( + web_contents(), &url_loader(), std::move(web_app_info), + /*is_locally_installed=*/false, WebappInstallSource::SYNC, base::BindLambdaForTesting( [&](const AppId& installed_app_id, InstallResultCode code) { EXPECT_EQ(InstallResultCode::kSuccessNewInstall, code); @@ -1162,21 +1166,26 @@ } } -TEST_F(WebAppInstallTaskTest, - InstallWebAppFromInfoRetrieveIcons_LocallyInstallled) { +TEST_F(WebAppInstallTaskTest, LoadAndInstallWebAppFromSync_LocallyInstallled) { { const auto url = GURL("https://example.com/"); + url_loader().SetNextLoadUrlResult( + url, WebAppUrlLoader::Result::kRedirectedUrlLoaded); CreateDataToRetrieve(url, /*open_as_window*/ false); auto app_id = - InstallWebAppFromInfoRetrieveIcons(url, /*is_locally_installed*/ false); + LoadAndInstallWebAppFromSync(url, /*is_locally_installed*/ false); EXPECT_FALSE(registrar().GetAppById(app_id)->is_locally_installed()); + EXPECT_EQ(registrar().GetAppDisplayMode(app_id), DisplayMode::kBrowser); } { const auto url = GURL("https://example.org/"); + url_loader().SetNextLoadUrlResult( + url, WebAppUrlLoader::Result::kRedirectedUrlLoaded); CreateDataToRetrieve(url, /*open_as_window*/ false); auto app_id = - InstallWebAppFromInfoRetrieveIcons(url, /*is_locally_installed*/ true); + LoadAndInstallWebAppFromSync(url, /*is_locally_installed*/ true); EXPECT_TRUE(registrar().GetAppById(app_id)->is_locally_installed()); + EXPECT_EQ(registrar().GetAppDisplayMode(app_id), DisplayMode::kBrowser); } }
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index cd1dc81..107b0ad 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -128,6 +128,13 @@ // Boolean that is true when user feedback to Google is allowed. const char kUserFeedbackAllowed[] = "feedback_allowed"; +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) && BUILDFLAG(ENABLE_EXTENSIONS) +// DictionaryValue that maps extension ids to the approved version of this +// extension for a supervised user. Missing extensions are not approved. +const char kSupervisedUserApprovedExtensions[] = + "profile.managed.approved_extensions"; +#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) && BUILDFLAG(ENABLE_EXTENSIONS) + // Stores the email address associated with the google account of the custodian // of the supervised user, set when the supervised user is created. const char kSupervisedUserCustodianEmail[] = "profile.managed.custodian_email";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index a63f8709..aad39d21 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -43,6 +43,9 @@ extern const char kSessionExitType[]; extern const char kObservedSessionTime[]; extern const char kSiteEngagementLastUpdateTime[]; +#if BUILDFLAG(ENABLE_SUPERVISED_USERS) && BUILDFLAG(ENABLE_EXTENSIONS) +extern const char kSupervisedUserApprovedExtensions[]; +#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) && BUILDFLAG(ENABLE_EXTENSIONS) extern const char kSupervisedUserCustodianEmail[]; extern const char kSupervisedUserCustodianName[]; extern const char kSupervisedUserCustodianObfuscatedGaiaId[];
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index e0d6965..77b97f0 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -429,6 +429,7 @@ const char kNetworkDetailSubPage[] = "networkDetail"; const char kNetworksSubPage[] = "networks"; const char kOsAccessibilitySubPage[] = "osAccessibility"; +const char kOsPrintingSubPage[] = "osPrinting"; const char kOsResetSubPage[] = "osReset"; const char kOsSearchSubPage[] = "osSearch"; const char kPluginVmDetailsSubPage[] = "pluginVm/details"; @@ -488,6 +489,7 @@ kOsLanguagesSubPage, kOsLanguagesDetailsSubPage, kOsLanguagesInputMethodsSubPage, + kOsPrintingSubPage, kOsResetSubPage, kOsSearchSubPage, kPointerOverlaySubPage,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 0fe1781..a8d1d76 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -389,6 +389,7 @@ extern const char kOsLanguagesSubPage[]; extern const char kOsLanguagesDetailsSubPage[]; extern const char kOsLanguagesInputMethodsSubPage[]; +extern const char kOsPrintingSubPage[]; extern const char kOsResetSubPage[]; extern const char kOsSearchSubPage[]; extern const char kPluginVmDetailsSubPage[];
diff --git a/chrome/services/app_service/app_service_impl.cc b/chrome/services/app_service/app_service_impl.cc index 1857f9a6..fcf5289 100644 --- a/chrome/services/app_service/app_service_impl.cc +++ b/chrome/services/app_service/app_service_impl.cc
@@ -137,6 +137,7 @@ void AppServiceImpl::LaunchAppWithIntent( apps::mojom::AppType app_type, const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) { @@ -144,8 +145,8 @@ if (iter == publishers_.end()) { return; } - iter->second->LaunchAppWithIntent(app_id, std::move(intent), launch_source, - display_id); + iter->second->LaunchAppWithIntent(app_id, event_flags, std::move(intent), + launch_source, display_id); } void AppServiceImpl::SetPermission(apps::mojom::AppType app_type,
diff --git a/chrome/services/app_service/app_service_impl.h b/chrome/services/app_service/app_service_impl.h index f12953a..85c97e5e 100644 --- a/chrome/services/app_service/app_service_impl.h +++ b/chrome/services/app_service/app_service_impl.h
@@ -63,6 +63,7 @@ apps::mojom::FilePathsPtr file_paths) override; void LaunchAppWithIntent(apps::mojom::AppType app_type, const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override;
diff --git a/chrome/services/app_service/app_service_impl_unittest.cc b/chrome/services/app_service/app_service_impl_unittest.cc index dffab48a..50baca4 100644 --- a/chrome/services/app_service/app_service_impl_unittest.cc +++ b/chrome/services/app_service/app_service_impl_unittest.cc
@@ -90,6 +90,7 @@ apps::mojom::FilePathsPtr file_paths) override {} void LaunchAppWithIntent(const std::string& app_id, + int32_t event_flags, apps::mojom::IntentPtr intent, apps::mojom::LaunchSource launch_source, int64_t display_id) override {}
diff --git a/chrome/services/app_service/public/cpp/intent_util.cc b/chrome/services/app_service/public/cpp/intent_util.cc index 3b6b749..315b0bd 100644 --- a/chrome/services/app_service/public/cpp/intent_util.cc +++ b/chrome/services/app_service/public/cpp/intent_util.cc
@@ -32,6 +32,7 @@ auto intent = apps::mojom::Intent::New(); intent->scheme = url.scheme(); intent->host = url.host(); + intent->port = url.port(); intent->path = url.path(); return intent; }
diff --git a/chrome/services/app_service/public/mojom/app_service.mojom b/chrome/services/app_service/public/mojom/app_service.mojom index 30e7465..0ff7c93 100644 --- a/chrome/services/app_service/public/mojom/app_service.mojom +++ b/chrome/services/app_service/public/mojom/app_service.mojom
@@ -54,6 +54,7 @@ LaunchAppWithIntent( AppType app_type, string app_id, + int32 event_flags, Intent intent, LaunchSource launch_source, int64 display_id); @@ -148,6 +149,7 @@ // of app platform. LaunchAppWithIntent( string app_id, + int32 event_flags, Intent intent, LaunchSource launch_source, int64 display_id);
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom index dc39c281..2fcf8aa 100644 --- a/chrome/services/app_service/public/mojom/types.mojom +++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -188,6 +188,7 @@ kFromMenu = 14, // Menu. kFromInstalledNotification = 15, // Installed notification kFromTest = 16, // Test + kFromArc = 17, // Arc. }; enum TriState { @@ -286,6 +287,7 @@ struct Intent { string? scheme; // URL scheme. e.g. https. string? host; // URL host. e.g. www.google.com. + string? port; // URL host. e.g. 8080. string? path; // URL path. e.g. /abc. };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 3bd43b5..cf539ef 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2425,6 +2425,7 @@ "../browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc", "../browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder_browsertest.cc", "../browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc", + "../browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc", "../browser/ui/webui/chromeos/login/discover/discover_browser_test.cc", "../browser/ui/webui/chromeos/login/discover/discover_browser_test.h", "../browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index 9f28b4e..c2586aa 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -13,6 +13,7 @@ #include "base/files/file_util.h" #include "base/location.h" #include "base/macros.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -752,14 +753,29 @@ return original_profile_; } -void TestingProfile::SetOffTheRecordProfile(std::unique_ptr<Profile> profile) { - DCHECK(!IsOffTheRecord()); - if (profile) - DCHECK_EQ(this, profile->GetOriginalProfile()); - incognito_profile_ = std::move(profile); +const Profile::OTRProfileID& TestingProfile::GetOTRProfileID() const { + // TODO(https://crbug.com//1033903): Remove this variable and add support for + // non-primary OTRs. + static base::NoDestructor<Profile::OTRProfileID> incognito_profile_id( + Profile::OTRProfileID::PrimaryID()); + DCHECK(IsOffTheRecord()); + + return *incognito_profile_id; } -Profile* TestingProfile::GetOffTheRecordProfile() { +void TestingProfile::SetOffTheRecordProfile( + std::unique_ptr<Profile> otr_profile) { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. + DCHECK(!IsOffTheRecord()); + if (otr_profile) + DCHECK_EQ(this, otr_profile->GetOriginalProfile()); + incognito_profile_ = std::move(otr_profile); +} + +Profile* TestingProfile::GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id) { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. + DCHECK(otr_profile_id == OTRProfileID::PrimaryID()); if (IsOffTheRecord()) return this; if (!incognito_profile_) @@ -767,11 +783,34 @@ return incognito_profile_.get(); } -void TestingProfile::DestroyOffTheRecordProfile() { +std::vector<Profile*> TestingProfile::GetAllOffTheRecordProfiles() { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. + std::vector<Profile*> otr_profiles; + + if (incognito_profile_) + otr_profiles.push_back(incognito_profile_.get()); + + return otr_profiles; +} + +void TestingProfile::DestroyOffTheRecordProfile(Profile* otr_profile) { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. incognito_profile_.reset(); } -bool TestingProfile::HasOffTheRecordProfile() { +void TestingProfile::DestroyOffTheRecordProfile() { + DestroyOffTheRecordProfile(incognito_profile_.get()); +} + +bool TestingProfile::HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id) { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. + DCHECK(otr_profile_id == OTRProfileID::PrimaryID()); + return incognito_profile_.get() != nullptr; +} + +bool TestingProfile::HasAnyOffTheRecordProfile() { + // TODO(https://crbug.com//1033903): Add support for non-primary OTRs. return incognito_profile_.get() != nullptr; } @@ -812,8 +851,7 @@ } bool TestingProfile::IsIndependentOffTheRecordProfile() { - return !GetOriginalProfile()->HasOffTheRecordProfile() || - GetOriginalProfile()->GetOffTheRecordProfile() != this; + return IsOffTheRecord() && GetOTRProfileID() != OTRProfileID::PrimaryID(); } bool TestingProfile::AllowsBrowserWindows() const {
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h index 7de6198..d288a67 100644 --- a/chrome/test/base/testing_profile.h +++ b/chrome/test/base/testing_profile.h
@@ -156,6 +156,9 @@ // Build an incognito profile, owned by |original_profile|. Note: unless you // need to customize the Builder, or access TestingProfile member functions, // you can use original_profile->GetOffTheRecordProfile(). + // + // TODO(https://crbug.com/1033903): Add BuildOffTheRecord to add possibility + // of creating non-primary OTRs. TestingProfile* BuildIncognito(TestingProfile* original_profile); private: @@ -268,10 +271,10 @@ void SetNetworkContext( std::unique_ptr<network::mojom::NetworkContext> network_context); - // Called on the parent of an incognito |profile|. Usually called from the - // constructor of an incognito TestingProfile, but can also be used by tests - // to provide an OffTheRecordProfileImpl instance. - void SetOffTheRecordProfile(std::unique_ptr<Profile> profile); + // Called on the parent of an OffTheRecord |otr_profile|. Usually called from + // the constructor of an OffTheRecord TestingProfile, but can also be used by + // tests to provide an OffTheRecordProfileImpl instance. + void SetOffTheRecordProfile(std::unique_ptr<Profile> otr_profile); void SetSupervisedUserId(const std::string& id); @@ -288,6 +291,7 @@ // profile dynamically. bool IsOffTheRecord() final; bool IsOffTheRecord() const final; + const OTRProfileID& GetOTRProfileID() const override; content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::ResourceContext* GetResourceContext() override; content::BrowserPluginGuestManager* GetGuestManager() override; @@ -315,9 +319,19 @@ std::string GetProfileUserName() const override; ProfileType GetProfileType() const override; - Profile* GetOffTheRecordProfile() override; - void DestroyOffTheRecordProfile() override; - bool HasOffTheRecordProfile() override; + // TODO(https://crbug.com/1033903): Remove the default value. + Profile* GetOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + std::vector<Profile*> GetAllOffTheRecordProfiles() override; + void DestroyOffTheRecordProfile(Profile* otr_profile) override; + // TODO(https://crbug.com/1033903): Remove this function when all the use + // cases are migrated to above version. The parameter-less version destroys + // the primary off the record profile. + void DestroyOffTheRecordProfile(); + // TODO(https://crbug.com/1033903): Remove the default value. + bool HasOffTheRecordProfile( + const OTRProfileID& otr_profile_id = OTRProfileID::PrimaryID()) override; + bool HasAnyOffTheRecordProfile() override; Profile* GetOriginalProfile() override; const Profile* GetOriginalProfile() const override; bool IsSupervised() const override;
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 4d3ca73..cd02eb3 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -261,6 +261,8 @@ "$root_gen_dir/chrome/test/data/webui/settings/protocol_handlers_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/recent_site_permissions_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/reset_page_test.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/reset_profile_banner_test.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/route_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/safety_check_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/search_engines_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/search_page_test.m.js", @@ -287,6 +289,7 @@ "$root_gen_dir/chrome/test/data/webui/settings/site_list_entry_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/site_list_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/site_settings_page_test.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/sync_account_control_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/sync_test_util.m.js", "$root_gen_dir/chrome/test/data/webui/settings/test_extension_control_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/settings/test_hats_browser_proxy.m.js",
diff --git a/chrome/test/data/webui/new_tab_page/logo_test.js b/chrome/test/data/webui/new_tab_page/logo_test.js index 6bb8a76..d68aa77d 100644 --- a/chrome/test/data/webui/new_tab_page/logo_test.js +++ b/chrome/test/data/webui/new_tab_page/logo_test.js
@@ -107,7 +107,8 @@ assertStyle(logo.$.multiColoredLogo, 'display', 'none'); }); - test('receiving resize message resizes doodle', async () => { + // Disabled for flakiness, see https://crbug.com/1065812. + test.skip('receiving resize message resizes doodle', async () => { // Arrange. const logo = await createLogo({content: {url: {url: 'https://foo.com'}}}); const transitionend = eventToPromise('transitionend', logo.$.iframe);
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js index b20c9f9..dc03db6 100644 --- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js +++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -156,7 +156,6 @@ } }; -// Disabled for flakiness, see https://crbug.com/1065812 -TEST_F('NewTabPageLogoTest', 'DISABLED_All', function() { +TEST_F('NewTabPageLogoTest', 'All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index 58cf12f..a55da60 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -56,6 +56,8 @@ "protocol_handlers_tests.js", "recent_site_permissions_test.js", "reset_page_test.js", + "reset_profile_banner_test.js", + "route_tests.js", "safety_check_page_test.js", "search_engines_page_test.js", "search_page_test.js", @@ -82,6 +84,7 @@ "site_favicon_test.js", "site_settings_page_test.js", "startup_urls_page_test.js", + "sync_account_control_test.js", "sync_test_util.js", "test_about_page_browser_proxy.js", "test_extension_control_browser_proxy.js", @@ -138,6 +141,7 @@ "autofill_test_util.makePasswordCheckStatus|makePasswordCheckStatus", "export_passwords_tests.run|run", "reset_page.TestResetBrowserProxy|TestResetBrowserProxy", + "settings.buildRouterForTesting|buildRouter", "settings.CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW", "settings.ChromeCleanupIdleReason|ChromeCleanupIdleReason", "settings.defaultSettingLabel|defaultSettingLabel", @@ -146,7 +150,9 @@ "settings.FakeSettingsPrivate|FakeSettingsPrivate", "settings.getFakeLanguagePrefs|getFakeLanguagePrefs", "settings.kMenuCloseDelay|kMenuCloseDelay", + "settings.MAX_SIGNIN_PROMO_IMPRESSION|MAX_SIGNIN_PROMO_IMPRESSION", "settings.setLanguageSettingsPrivateApiForTest|setLanguageSettingsPrivateApiForTest", + "settings.setPageVisibilityForTesting|setPageVisibilityForTesting", "settings.setSearchManagerForTesting|setSearchManagerForTesting", "settings.TestLanguagesBrowserProxy|TestLanguagesBrowserProxy", "settings.TestLifetimeBrowserProxy|TestLifetimeBrowserProxy",
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index e001a1fc..fb4ca63 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1982,7 +1982,7 @@ }; TEST_F('CrSettingsRouteTest', 'All', function() { - mocha.run(); + runMochaSuite('route'); }); /** @@ -1992,7 +1992,7 @@ function CrSettingsNonExistentRouteTest() {} CrSettingsNonExistentRouteTest.prototype = { - __proto__: CrSettingsBrowserTest.prototype, + __proto__: CrSettingsRouteTest.prototype, /** @override */ browsePreload: 'chrome://settings/non/existent/route', @@ -2005,15 +2005,7 @@ GEN('#define MAYBE_NonExistentRoute NonExistentRoute'); GEN('#endif'); TEST_F('CrSettingsNonExistentRouteTest', 'MAYBE_NonExistentRoute', function() { - suite('NonExistentRoutes', function() { - test('redirect to basic', function() { - assertEquals( - settings.routes.BASIC, - settings.Router.getInstance().getCurrentRoute()); - assertEquals('/', location.pathname); - }); - }); - mocha.run(); + runMochaSuite('NonExistentRoute'); }); /** @@ -2023,56 +2015,14 @@ function CrSettingsRouteDynamicParametersTest() {} CrSettingsRouteDynamicParametersTest.prototype = { - __proto__: CrSettingsBrowserTest.prototype, + __proto__: CrSettingsRouteTest.prototype, /** @override */ browsePreload: 'chrome://settings/search?guid=a%2Fb&foo=42', }; TEST_F('CrSettingsRouteDynamicParametersTest', 'All', function() { - suite('DynamicParameters', function() { - test('get parameters from URL and navigation', function(done) { - assertEquals( - settings.routes.SEARCH, - settings.Router.getInstance().getCurrentRoute()); - assertEquals( - 'a/b', - settings.Router.getInstance().getQueryParameters().get('guid')); - assertEquals( - '42', settings.Router.getInstance().getQueryParameters().get('foo')); - - const params = new URLSearchParams(); - params.set('bar', 'b=z'); - params.set('biz', '3'); - settings.Router.getInstance().navigateTo( - settings.routes.SEARCH_ENGINES, params); - assertEquals( - settings.routes.SEARCH_ENGINES, - settings.Router.getInstance().getCurrentRoute()); - assertEquals( - 'b=z', settings.Router.getInstance().getQueryParameters().get('bar')); - assertEquals( - '3', settings.Router.getInstance().getQueryParameters().get('biz')); - assertEquals('?bar=b%3Dz&biz=3', window.location.search); - - window.addEventListener('popstate', function(event) { - assertEquals( - '/search', settings.Router.getInstance().getCurrentRoute().path); - assertEquals( - settings.routes.SEARCH, - settings.Router.getInstance().getCurrentRoute()); - assertEquals( - 'a/b', - settings.Router.getInstance().getQueryParameters().get('guid')); - assertEquals( - '42', - settings.Router.getInstance().getQueryParameters().get('foo')); - done(); - }); - window.history.back(); - }); - }); - mocha.run(); + runMochaSuite('DynamicParameters'); }); /**
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js index 6e538e8d..4b3ecb9 100644 --- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -354,6 +354,34 @@ runMochaSuite('HappinessTrackingSurveys'); }); +// eslint-disable-next-line no-var +var CrSettingsRouteV3Test = class extends CrSettingsV3BrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://settings/test_loader.html?module=settings/route_tests.m.js'; + } +}; + +TEST_F('CrSettingsRouteV3Test', 'Basic', function() { + runMochaSuite('route'); +}); + +TEST_F('CrSettingsRouteV3Test', 'DynamicParameters', function() { + runMochaSuite('DynamicParameters'); +}); + +// Copied from Polymer 2 test: +// Failing on ChromiumOS dbg. https://crbug.com/709442 +GEN('#if (defined(OS_WIN) || defined(OS_CHROMEOS)) && !defined(NDEBUG)'); +GEN('#define MAYBE_NonExistentRoute DISABLED_NonExistentRoute'); +GEN('#else'); +GEN('#define MAYBE_NonExistentRoute NonExistentRoute'); +GEN('#endif'); + +TEST_F('CrSettingsRouteV3Test', 'MAYBE_NonExistentRoute', function() { + runMochaSuite('NonExistentRoute'); +}); + [['AllSites', 'all_sites_tests.m.js'], ['AppearanceFontsPage', 'appearance_fonts_page_test.m.js'], ['AppearancePage', 'appearance_page_test.m.js'], @@ -385,6 +413,7 @@ ['ProtocolHandlers', 'protocol_handlers_tests.m.js'], ['RecentSitePermissions', 'recent_site_permissions_test.m.js'], ['ResetPage', 'reset_page_test.m.js'], + ['ResetProfileBanner', 'reset_profile_banner_test.m.js'], ['SearchEngines', 'search_engines_page_test.m.js'], ['SearchPage', 'search_page_test.m.js'], ['Search', 'search_settings_test.m.js'], @@ -402,6 +431,7 @@ ['Slider', 'settings_slider_tests.m.js'], ['StartupUrlsPage', 'startup_urls_page_test.m.js'], ['Subpage', 'settings_subpage_test.m.js'], + ['SyncAccountControl', 'sync_account_control_test.m.js'], ['Textarea', 'settings_textarea_tests.m.js'], ['ToggleButton', 'settings_toggle_button_tests.m.js'], ['ZoomLevels', 'zoom_levels_tests.m.js'],
diff --git a/chrome/test/data/webui/settings/reset_profile_banner_test.js b/chrome/test/data/webui/settings/reset_profile_banner_test.js index a437c7e..62c0b30 100644 --- a/chrome/test/data/webui/settings/reset_profile_banner_test.js +++ b/chrome/test/data/webui/settings/reset_profile_banner_test.js
@@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {Router, routes, ResetBrowserProxyImpl} from 'chrome://settings/settings.js'; +// #import {TestResetBrowserProxy} from 'chrome://test/settings/test_reset_browser_proxy.m.js'; +// clang-format on + suite('BannerTests', function() { let resetBanner = null; let browserProxy = null;
diff --git a/chrome/test/data/webui/settings/route_tests.js b/chrome/test/data/webui/settings/route_tests.js index 7b538cc..133c434 100644 --- a/chrome/test/data/webui/settings/route_tests.js +++ b/chrome/test/data/webui/settings/route_tests.js
@@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {buildRouter, pageVisibility, routes, Route, Router, setPageVisibilityForTesting} from 'chrome://settings/settings.js'; +// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +// clang-format on + suite('route', function() { /** * Returns a new promise that resolves after a window 'popstate' event. @@ -214,13 +219,13 @@ }); test('pageVisibility affects route availability', function() { - settings.pageVisibility = { + settings.setPageVisibilityForTesting({ appearance: false, autofill: false, defaultBrowser: false, onStartup: false, reset: false, - }; + }); loadTimeData.overrideValues({showOSSettings: false}); const router = settings.buildRouterForTesting(); @@ -257,3 +262,74 @@ settings.routes.LANGUAGES.getAbsolutePath()); }); }); + +suite('DynamicParameters', function() { + setup(function() { + // TODO(https://crbug.com/1026426): Remove conditional when Polymer 2 tests + // are no longer run. + if (window.location.pathname === '/test_loader.html') { + PolymerTest.clearBody(); + window.history.replaceState({}, '', 'search?guid=a%2Fb&foo=42'); + const settingsUi = document.createElement('settings-ui'); + document.body.appendChild(settingsUi); + } + }); + + test('get parameters from URL and navigation', function(done) { + assertEquals( + settings.routes.SEARCH, + settings.Router.getInstance().getCurrentRoute()); + assertEquals( + 'a/b', settings.Router.getInstance().getQueryParameters().get('guid')); + assertEquals( + '42', settings.Router.getInstance().getQueryParameters().get('foo')); + + const params = new URLSearchParams(); + params.set('bar', 'b=z'); + params.set('biz', '3'); + settings.Router.getInstance().navigateTo( + settings.routes.SEARCH_ENGINES, params); + assertEquals( + settings.routes.SEARCH_ENGINES, + settings.Router.getInstance().getCurrentRoute()); + assertEquals( + 'b=z', settings.Router.getInstance().getQueryParameters().get('bar')); + assertEquals( + '3', settings.Router.getInstance().getQueryParameters().get('biz')); + assertEquals('?bar=b%3Dz&biz=3', window.location.search); + + window.addEventListener('popstate', function(event) { + assertEquals( + '/search', settings.Router.getInstance().getCurrentRoute().path); + assertEquals( + settings.routes.SEARCH, + settings.Router.getInstance().getCurrentRoute()); + assertEquals( + 'a/b', + settings.Router.getInstance().getQueryParameters().get('guid')); + assertEquals( + '42', settings.Router.getInstance().getQueryParameters().get('foo')); + done(); + }); + window.history.back(); + }); +}); + +suite('NonExistentRoute', function() { + setup(function() { + // TODO(https://crbug.com/1026426): Remove conditional when Polymer 2 tests + // are no longer run. + if (window.location.pathname === '/test_loader.html') { + PolymerTest.clearBody(); + window.history.replaceState({}, '', 'non/existent/route'); + const settingsUi = document.createElement('settings-ui'); + document.body.appendChild(settingsUi); + } + }); + + test('redirect to basic', function() { + assertEquals( + settings.routes.BASIC, settings.Router.getInstance().getCurrentRoute()); + assertEquals('/', location.pathname); + }); +});
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js index fe8387a..7c4b134 100644 --- a/chrome/test/data/webui/settings/sync_account_control_test.js +++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -2,6 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {Router, routes, SyncBrowserProxyImpl, StatusAction} from 'chrome://settings/settings.js'; +// #import {MAX_SIGNIN_PROMO_IMPRESSION} from 'chrome://settings/lazy_load.js'; +// #import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +// #import {setupRouterWithSyncRoutes, simulateStoredAccounts} from 'chrome://test/settings/sync_test_util.m.js'; +// #import {isChildVisible, isVisible} from 'chrome://test/test_util.m.js'; +// clang-format on + +// TODO(https://crbug.com/1063530): Remove all ignores in this file, once +// i18nPolymer works correctly in Polymer 3. cr.define('settings_sync_account_control', function() { suite('SyncAccountControl', function() { @@ -160,10 +172,10 @@ // Avatar row shows the right account. assertTrue(test_util.isChildVisible(testElement, '#promo-header')); assertTrue(test_util.isChildVisible(testElement, '#avatar-row')); - assertTrue(userInfo.textContent.includes('fooName')); - assertTrue(userInfo.textContent.includes('foo@foo.com')); - assertFalse(userInfo.textContent.includes('barName')); - assertFalse(userInfo.textContent.includes('bar@bar.com')); + /* #ignore */ assertTrue(userInfo.textContent.includes('fooName')); + /* #ignore */ assertTrue(userInfo.textContent.includes('foo@foo.com')); + /* #ignore */ assertFalse(userInfo.textContent.includes('barName')); + /* #ignore */ assertFalse(userInfo.textContent.includes('bar@bar.com')); // Menu contains the right items. assertTrue(!!testElement.$$('#menu')); @@ -201,10 +213,13 @@ // email. items[1].click(); Polymer.dom.flush(); - assertFalse(userInfo.textContent.includes('fooName')); - assertFalse(userInfo.textContent.includes('foo@foo.com')); - assertTrue(userInfo.textContent.includes('barName')); - assertTrue(userInfo.textContent.includes('bar@bar.com')); + /* #ignore */ assertFalse( + /* #ignore */ userInfo.textContent.includes('fooName')); + /* #ignore */ assertFalse( + /* #ignore */ userInfo.textContent.includes('foo@foo.com')); + /* #ignore */ assertTrue(userInfo.textContent.includes('barName')); + /* #ignore */ assertTrue( + /* #ignore */ userInfo.textContent.includes('bar@bar.com')); assertTrue(test_util.isVisible(syncButton)); browserProxy.resetResolver('startSyncingWithEmail'); @@ -248,10 +263,10 @@ } const userInfo = testElement.$$('#user-info'); - assertTrue(userInfo.textContent.includes('barName')); - assertTrue(userInfo.textContent.includes('bar@bar.com')); - assertFalse(userInfo.textContent.includes('fooName')); - assertFalse(userInfo.textContent.includes('foo@foo.com')); + /* #ignore */ assertTrue(userInfo.textContent.includes('barName')); + /* #ignore */ assertTrue(userInfo.textContent.includes('bar@bar.com')); + /* #ignore */ assertFalse(userInfo.textContent.includes('fooName')); + /* #ignore */ assertFalse(userInfo.textContent.includes('foo@foo.com')); assertFalse(test_util.isChildVisible(testElement, '#sync-button')); assertTrue(test_util.isChildVisible(testElement, '#turn-off')); @@ -262,7 +277,7 @@ assertEquals( settings.Router.getInstance().getCurrentRoute(), - settings.routes.SIGN_OUT); + settings.Router.getInstance().getRoutes().SIGN_OUT); }); test('signed in, has error', function() { @@ -283,9 +298,9 @@ assertTrue(!!testElement.$$('[icon="settings:sync-problem"]')); let displayedText = userInfo.querySelector('span:not([hidden])').textContent; - assertFalse(displayedText.includes('barName')); - assertFalse(displayedText.includes('fooName')); - assertTrue(displayedText.includes('Sync isn\'t working')); + /* #ignore */ assertFalse(displayedText.includes('barName')); + /* #ignore */ assertFalse(displayedText.includes('fooName')); + /* #ignore */ assertTrue(displayedText.includes('Sync isn\'t working')); // The sync error button is shown to resolve the error. assertTrue(test_util.isChildVisible(testElement, '#sync-error-button')); @@ -302,9 +317,9 @@ .classList.contains('sync-paused')); assertTrue(!!testElement.$$('[icon=\'settings:sync-disabled\']')); displayedText = userInfo.querySelector('span:not([hidden])').textContent; - assertFalse(displayedText.includes('barName')); - assertFalse(displayedText.includes('fooName')); - assertTrue(displayedText.includes('Sync is paused')); + /* #ignore */ assertFalse(displayedText.includes('barName')); + /* #ignore */ assertFalse(displayedText.includes('fooName')); + /* #ignore */ assertTrue(displayedText.includes('Sync is paused')); // The sync error button is shown to resolve the error. assertTrue(test_util.isChildVisible(testElement, '#sync-error-button')); @@ -322,9 +337,9 @@ .classList.contains('sync-disabled')); assertTrue(!!testElement.$$('[icon=\'cr:sync\']')); displayedText = userInfo.querySelector('span:not([hidden])').textContent; - assertFalse(displayedText.includes('barName')); - assertFalse(displayedText.includes('fooName')); - assertTrue(displayedText.includes('Sync disabled')); + /* #ignore */ assertFalse(displayedText.includes('barName')); + /* #ignore */ assertFalse(displayedText.includes('fooName')); + /* #ignore */ assertTrue(displayedText.includes('Sync disabled')); assertFalse(test_util.isChildVisible(testElement, '#sync-error-button')); testElement.syncStatus = { @@ -340,9 +355,9 @@ .classList.contains('sync-problem')); assertTrue(!!testElement.$$('[icon="settings:sync-problem"]')); displayedText = userInfo.querySelector('span:not([hidden])').textContent; - assertFalse(displayedText.includes('barName')); - assertFalse(displayedText.includes('fooName')); - assertTrue(displayedText.includes('Sync isn\'t working')); + /* #ignore */ assertFalse(displayedText.includes('barName')); + /* #ignore */ assertFalse(displayedText.includes('fooName')); + /* #ignore */ assertTrue(displayedText.includes('Sync isn\'t working')); testElement.syncStatus = { firstSetupInProgress: false, @@ -358,10 +373,11 @@ .classList.contains('sync-problem')); assertTrue(!!testElement.$$('[icon="settings:sync-problem"]')); displayedText = userInfo.querySelector('span:not([hidden])').textContent; - assertFalse(displayedText.includes('barName')); - assertFalse(displayedText.includes('fooName')); - assertFalse(displayedText.includes('Sync isn\'t working')); - assertTrue(displayedText.includes('Error syncing passwords')); + /* #ignore */ assertFalse(displayedText.includes('barName')); + /* #ignore */ assertFalse(displayedText.includes('fooName')); + /* #ignore */ assertFalse(displayedText.includes('Sync isn\'t working')); + /* #ignore */ assertTrue( + /* #ignore */ displayedText.includes('Error syncing passwords')); // The sync error button is shown to resolve the error. assertTrue(test_util.isChildVisible(testElement, '#sync-error-button')); assertTrue(test_util.isChildVisible(testElement, '#turn-off')); @@ -382,8 +398,9 @@ const userInfo = testElement.$$('#user-info'); const setupButtons = testElement.$$('#setup-buttons'); - assertTrue(userInfo.textContent.includes('barName')); - assertTrue(userInfo.textContent.includes('Setup in progress...')); + /* #ignore */ assertTrue(userInfo.textContent.includes('barName')); + /* #ignore */ assertTrue( + /* #ignore */ userInfo.textContent.includes('Setup in progress...')); assertTrue(test_util.isVisible(setupButtons)); }); @@ -508,4 +525,5 @@ assertTrue(testElement.$$('#sign-in').disabled); }); }); + // #cr_define_end });
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index ad2d4745..6846387 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -16,7 +16,9 @@ #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_launch_params.h" -#include "chrome/browser/apps/launch_service/launch_service.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/profiles/profile.h" @@ -2284,7 +2286,9 @@ WindowOpenDisposition::NEW_WINDOW, apps::mojom::AppLaunchSource::kSourceTest); params.command_line = *base::CommandLine::ForCurrentProcess(); - apps::LaunchService::Get(browser()->profile())->OpenApplication(params); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->BrowserAppLauncher() + .LaunchAppWithParams(params); } void RunTests(const std::string& extension_dirname) {
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index cde1a2e..78cc3299 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -298,9 +298,9 @@ const base::Feature kShowPlayInDemoMode{"ShowPlayInDemoMode", base::FEATURE_ENABLED_BY_DEFAULT}; -// Shows the progress bar during Demo Mode setup. -const base::Feature kShowProgressBarInDemoModeSetup{ - "ShowProgressBarInDemoModeSetup", base::FEATURE_DISABLED_BY_DEFAULT}; +// Shows individual steps during Demo Mode setup. +const base::Feature kShowStepsInDemoModeSetup{ + "ShowStepsInDemoModeSetup", base::FEATURE_DISABLED_BY_DEFAULT}; // Uses experimental component version for smart dim. const base::Feature kSmartDimExperimentalComponent{
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 2dbed49..d2799637 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -136,7 +136,7 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kShowPlayInDemoMode; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) -extern const base::Feature kShowProgressBarInDemoModeSetup; +extern const base::Feature kShowStepsInDemoModeSetup; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kSmartDimExperimentalComponent; COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
diff --git a/components/arc/mojom/intent_helper.mojom b/components/arc/mojom/intent_helper.mojom index 87a74291..2916146 100644 --- a/components/arc/mojom/intent_helper.mojom +++ b/components/arc/mojom/intent_helper.mojom
@@ -173,14 +173,16 @@ AMBIENTMODE, PLUGINVMDETAILS, PLUGINVMSHAREDPATHS, - OSRESET, OSACCESSIBILITY, OSLANGUAGES, OSLANGUAGESDETAILS, OSLANGUAGESINPUTMETHODS, + OSPRINTING, + PRINTING, OSSEARCH, + OSRESET, - LAST = OSSEARCH, + LAST = OSRESET, }; // Describes an unique chrome app.
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index aa4c9ee5..4e295f5 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -139,6 +139,8 @@ "state.h", "string_conversions_util.cc", "string_conversions_util.h", + "switches.cc", + "switches.h", "top_padding.cc", "top_padding.h", "trigger_context.cc", @@ -219,6 +221,7 @@ "//base", "//base/test:test_support", "//components/autofill/core/browser:test_support", + "//components/version_info", "//testing/gmock", "//testing/gtest", ]
diff --git a/components/autofill_assistant/browser/DEPS b/components/autofill_assistant/browser/DEPS index 6f760c5..82a5fd1 100644 --- a/components/autofill_assistant/browser/DEPS +++ b/components/autofill_assistant/browser/DEPS
@@ -2,7 +2,7 @@ "+chrome/android/features/autofill_assistant/test_support_jni_headers", "+components/autofill", "+components/password_manager/core/browser", - "+components/version_info/version_info.h", + "+components/version_info", "+content/public/browser", "+content/public/test", "+content/shell/browser/shell.h",
diff --git a/components/autofill_assistant/browser/client.h b/components/autofill_assistant/browser/client.h index dfb11fb..e8345ec 100644 --- a/components/autofill_assistant/browser/client.h +++ b/components/autofill_assistant/browser/client.h
@@ -17,7 +17,11 @@ namespace password_manager { class PasswordManagerClient; -} +} // namespace password_manager + +namespace version_info { +enum class Channel; +} // namespace version_info namespace autofill_assistant { class AccessTokenFetcher; @@ -38,8 +42,9 @@ // Destroys the UI immediately. virtual void DestroyUI() = 0; - // Returns the API key to be used for requests to the backend. - virtual std::string GetApiKey() const = 0; + // Returns the channel for the installation (canary, dev, beta, stable). + // Returns unknown otherwise. + virtual version_info::Channel GetChannel() const = 0; // Returns the e-mail address that corresponds to the auth credentials. Might // be empty. @@ -58,9 +63,6 @@ // Returns the currently active login fetcher. virtual WebsiteLoginFetcher* GetWebsiteLoginFetcher() const = 0; - // Returns the server URL to be used for requests to the backend. - virtual std::string GetServerUrl() const = 0; - // Returns the locale. virtual std::string GetLocale() const = 0;
diff --git a/components/autofill_assistant/browser/mock_client.h b/components/autofill_assistant/browser/mock_client.h index 3d595ed3..40470c7 100644 --- a/components/autofill_assistant/browser/mock_client.h +++ b/components/autofill_assistant/browser/mock_client.h
@@ -11,6 +11,7 @@ #include "components/autofill_assistant/browser/metrics.h" #include "components/autofill_assistant/browser/mock_personal_data_manager.h" #include "components/autofill_assistant/browser/website_login_fetcher.h" +#include "components/version_info/channel.h" #include "testing/gmock/include/gmock/gmock.h" namespace autofill_assistant { @@ -20,8 +21,7 @@ MockClient(); ~MockClient(); - MOCK_CONST_METHOD0(GetApiKey, std::string()); - MOCK_CONST_METHOD0(GetServerUrl, std::string()); + MOCK_CONST_METHOD0(GetChannel, version_info::Channel()); MOCK_CONST_METHOD0(GetLocale, std::string()); MOCK_CONST_METHOD0(GetCountryCode, std::string()); MOCK_CONST_METHOD0(GetDeviceContext, DeviceContext());
diff --git a/components/autofill_assistant/browser/service_impl.cc b/components/autofill_assistant/browser/service_impl.cc index 720cecd4..439b2c44 100644 --- a/components/autofill_assistant/browser/service_impl.cc +++ b/components/autofill_assistant/browser/service_impl.cc
@@ -15,24 +15,24 @@ #include "base/strings/stringprintf.h" #include "components/autofill_assistant/browser/client.h" #include "components/autofill_assistant/browser/protocol_utils.h" +#include "components/autofill_assistant/browser/switches.h" #include "components/autofill_assistant/browser/trigger_context.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" #include "crypto/sha2.h" +#include "google_apis/google_api_keys.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/url_canon_stdstring.h" +namespace autofill_assistant { namespace { -namespace switches { -// --autofill_assistant-auth=false disables authentication. This is only useful -// during development, as prod instances require authentication. -const char* const kAutofillAssistantAuth = "autofill-assistant-auth"; -} // namespace switches +const char* const kDefaultAutofillAssistantServerUrl = + "https://automate-pa.googleapis.com"; const char* const kScriptEndpoint = "/v1/supportsSite2"; const char* const kActionEndpoint = "/v1/actions2"; @@ -54,21 +54,45 @@ "This feature can be disabled in settings." policy_exception_justification: "Not implemented." })"); -} // namespace -namespace autofill_assistant { +std::string GetAPIKey(version_info::Channel channel) { + const auto* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kAutofillAssistantServerKey)) { + return command_line->GetSwitchValueASCII( + switches::kAutofillAssistantServerKey); + } + + if (google_apis::IsGoogleChromeAPIKeyUsed()) { + return channel == version_info::Channel::STABLE + ? google_apis::GetAPIKey() + : google_apis::GetNonStableAPIKey(); + } + return ""; +} + +std::string GetServerUrl() { + std::string server_url = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kAutofillAssistantUrl); + if (server_url.empty()) { + server_url = kDefaultAutofillAssistantServerUrl; + } + return server_url; +} + +} // namespace // static std::unique_ptr<ServiceImpl> ServiceImpl::Create( content::BrowserContext* context, Client* client) { - GURL server_url(client->GetServerUrl()); + GURL server_url(GetServerUrl()); DCHECK(server_url.is_valid()); return std::make_unique<ServiceImpl>( - client->GetApiKey(), server_url, context, client->GetAccessTokenFetcher(), - client->GetLocale(), client->GetCountryCode(), client->GetDeviceContext(), - client); + GetAPIKey(client->GetChannel()), server_url, context, + client->GetAccessTokenFetcher(), client->GetLocale(), + client->GetCountryCode(), client->GetDeviceContext(), client); } ServiceImpl::ServiceImpl(const std::string& api_key,
diff --git a/components/autofill_assistant/browser/service_impl_unittest.cc b/components/autofill_assistant/browser/service_impl_unittest.cc index f5616a48..031ef051 100644 --- a/components/autofill_assistant/browser/service_impl_unittest.cc +++ b/components/autofill_assistant/browser/service_impl_unittest.cc
@@ -19,9 +19,6 @@ class ServiceImplTest : public ::testing::Test { public: ServiceImplTest() { - ON_CALL(mock_client_, GetServerUrl) - .WillByDefault(Return("https://www.google.com/")); - service_impl_ = ServiceImpl::Create(nullptr, &mock_client_); }
diff --git a/components/autofill_assistant/browser/switches.cc b/components/autofill_assistant/browser/switches.cc new file mode 100644 index 0000000..da90dfb8 --- /dev/null +++ b/components/autofill_assistant/browser/switches.cc
@@ -0,0 +1,22 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill_assistant/browser/switches.h" + +namespace autofill_assistant { +namespace switches { + +// Sets the API key to be used instead of Chrome's default key when sending +// requests to the backend. +const char kAutofillAssistantServerKey[] = "autofill-assistant-key"; + +// Overrides the default backend URL. +const char kAutofillAssistantUrl[] = "autofill-assistant-url"; + +// Disables authentication when set to false. This is only useful +// during development, as prod instances require authentication. +const char kAutofillAssistantAuth[] = "autofill-assistant-auth"; + +} // namespace switches +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/switches.h b/components/autofill_assistant/browser/switches.h new file mode 100644 index 0000000..b966fbc2 --- /dev/null +++ b/components/autofill_assistant/browser/switches.h
@@ -0,0 +1,18 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_SWITCHES_H_ +#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_SWITCHES_H_ + +namespace autofill_assistant { +namespace switches { + +extern const char kAutofillAssistantServerKey[]; +extern const char kAutofillAssistantUrl[]; +extern const char kAutofillAssistantAuth[]; + +} // namespace switches +} // namespace autofill_assistant + +#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_SWITCHES_H_
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index db9e57a..661b9c2 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -48,7 +48,7 @@ private static final String TAG = "UrlHandler"; // Enables debug logging on a local build. - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; private static final String WTAI_URL_PREFIX = "wtai://wp/"; private static final String WTAI_MC_URL_PREFIX = "wtai://wp/mc;";
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc index 5b0de0c..d4e32d8 100644 --- a/components/gcm_driver/gcm_driver_desktop.cc +++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -1064,7 +1064,6 @@ // codes, the instance ID will assume no current ID and generate a new one // if the gcm client is not ready and we pass an empty string to the callback // below. We should fix this! - UMA_HISTOGRAM_ENUMERATION("GCM.GetInstanceIDData.ClientStarted", result); if (result != GCMClient::SUCCESS) { DLOG(ERROR) << "Unable to get the InstanceID data: cannot start the GCM Client";
diff --git a/components/password_manager/core/browser/password_generation_manager.cc b/components/password_manager/core/browser/password_generation_manager.cc index 93622ac8..8dcabc5 100644 --- a/components/password_manager/core/browser/password_generation_manager.cc +++ b/components/password_manager/core/browser/password_generation_manager.cc
@@ -19,8 +19,6 @@ namespace { using autofill::PasswordForm; -using metrics_util::GenerationPresaveConflict; -using metrics_util::LogGenerationPresaveConflict; std::vector<PasswordForm> DeepCopyVector( const std::vector<const PasswordForm*>& forms) { @@ -132,7 +130,6 @@ } void PasswordDataForUI::Save() { - LogPresavedUpdateUIDismissalReason(metrics_util::CLICKED_SAVE); bubble_interaction_cb_.Run(true, pending_form_); } @@ -152,17 +149,14 @@ } void PasswordDataForUI::OnNopeUpdateClicked() { - LogPresavedUpdateUIDismissalReason(metrics_util::CLICKED_CANCEL); bubble_interaction_cb_.Run(false, pending_form_); } void PasswordDataForUI::OnNeverClicked() { - LogPresavedUpdateUIDismissalReason(metrics_util::CLICKED_NEVER); bubble_interaction_cb_.Run(false, pending_form_); } void PasswordDataForUI::OnNoInteraction(bool is_update) { - LogPresavedUpdateUIDismissalReason(metrics_util::NO_DIRECT_INTERACTION); bubble_interaction_cb_.Run(false, pending_form_); } @@ -209,8 +203,6 @@ const PasswordForm* conflict = FindUsernameConflict(generated, non_federated_matches); if (conflict) { - LogGenerationPresaveConflict( - GenerationPresaveConflict::kConflictWithEmptyUsername); auto bubble_launcher = std::make_unique<PasswordDataForUI>( std::move(generated), non_federated_matches, federated_matches, base::BindRepeating(&PasswordGenerationManager::OnPresaveBubbleResult, @@ -218,13 +210,7 @@ client_->PromptUserToSaveOrUpdatePassword(std::move(bubble_launcher), true); return; - } else { - LogGenerationPresaveConflict( - GenerationPresaveConflict::kNoConflictWithEmptyUsername); } - } else { - LogGenerationPresaveConflict( - GenerationPresaveConflict::kNoUsernameConflict); } driver->GeneratedPasswordAccepted(generated.password_value); }
diff --git a/components/password_manager/core/browser/password_generation_manager_unittest.cc b/components/password_manager/core/browser/password_generation_manager_unittest.cc index 0283127a..d3713c1 100644 --- a/components/password_manager/core/browser/password_generation_manager_unittest.cc +++ b/components/password_manager/core/browser/password_generation_manager_unittest.cc
@@ -6,7 +6,6 @@ #include "base/memory/scoped_refptr.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" #include "base/test/task_environment.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" @@ -176,7 +175,6 @@ // Check that accepting a generated password simply relays the message to the // driver. TEST_F(PasswordGenerationManagerTest, GeneratedPasswordAccepted_EmptyStore) { - base::HistogramTester histogram_tester; PasswordForm generated = CreateGenerated(); MockPasswordManagerDriver driver; FakeFormFetcher fetcher; @@ -186,16 +184,12 @@ std::move(generated), fetcher.GetNonFederatedMatches(), fetcher.GetFederatedMatches(), driver.AsWeakPtr()); EXPECT_FALSE(manager().HasGeneratedPassword()); - histogram_tester.ExpectUniqueSample( - "PasswordGeneration.PresaveConflict", - metrics_util::GenerationPresaveConflict::kNoUsernameConflict, 1); } // In case of accepted password conflicts with an existing username the // credential can be presaved with an empty one. Thus, no conflict happens and // the driver should be notified directly. TEST_F(PasswordGenerationManagerTest, GeneratedPasswordAccepted_Conflict) { - base::HistogramTester histogram_tester; PasswordForm generated = CreateGenerated(); const PasswordForm saved = CreateSaved(); generated.username_value = saved.username_value; @@ -208,13 +202,9 @@ std::move(generated), fetcher.GetNonFederatedMatches(), fetcher.GetFederatedMatches(), driver.AsWeakPtr()); EXPECT_FALSE(manager().HasGeneratedPassword()); - histogram_tester.ExpectUniqueSample( - "PasswordGeneration.PresaveConflict", - metrics_util::GenerationPresaveConflict::kNoConflictWithEmptyUsername, 1); } TEST_F(PasswordGenerationManagerTest, GeneratedPasswordAccepted_UpdateUI) { - base::HistogramTester histogram_tester; MockPasswordManagerDriver driver; EXPECT_CALL(driver, GeneratedPasswordAccepted(_)).Times(0); std::unique_ptr<PasswordFormManagerForUI> ui_form = @@ -231,9 +221,6 @@ ui_form->GetPendingCredentials().password_value); EXPECT_THAT(ui_form->GetInteractionsStats(), IsEmpty()); EXPECT_FALSE(ui_form->IsBlacklisted()); - histogram_tester.ExpectUniqueSample( - "PasswordGeneration.PresaveConflict", - metrics_util::GenerationPresaveConflict::kConflictWithEmptyUsername, 1); } TEST_F(PasswordGenerationManagerTest,
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index b327c6b..5e479a1 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -43,12 +43,6 @@ reason, NUM_UI_RESPONSES); } -void LogPresavedUpdateUIDismissalReason(UIDismissalReason reason) { - base::UmaHistogramEnumeration( - "PasswordManager.PresavedUpdateUIDismissalReason", reason, - NUM_UI_RESPONSES); -} - void LogLeakDialogTypeAndDismissalReason(LeakDialogType type, LeakDialogDismissalReason reason) { static constexpr char kHistogram[] = @@ -243,10 +237,6 @@ value); } -void LogGenerationPresaveConflict(GenerationPresaveConflict value) { - base::UmaHistogramEnumeration("PasswordGeneration.PresaveConflict", value); -} - void LogGenerationDialogChoice(GenerationDialogChoice choice, PasswordGenerationType type) { switch (type) {
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 56edd89..c0d4b8f 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -433,18 +433,6 @@ kMaxValue = kRejected }; -// Type of the conflict with existing credentials when starting password -// generation. -enum class GenerationPresaveConflict { - // Credential can be presaved as is. - kNoUsernameConflict = 0, - // Credential can be presaved without username. - kNoConflictWithEmptyUsername = 1, - // Credential should overwrite one without username. - kConflictWithEmptyUsername = 2, - kMaxValue = kConflictWithEmptyUsername -}; - // Log the |reason| a user dismissed the password manager UI except save/update // bubbles. void LogGeneralUIDismissalReason(UIDismissalReason reason); @@ -455,10 +443,6 @@ // Log the |reason| a user dismissed the update password bubble. void LogUpdateUIDismissalReason(UIDismissalReason reason); -// Log the |reason| a user dismissed the update password bubble when resolving a -// conflict during generation. -void LogPresavedUpdateUIDismissalReason(UIDismissalReason reason); - // Log the |type| of a leak dialog shown to the user and the |reason| why it was // dismissed. void LogLeakDialogTypeAndDismissalReason(LeakDialogType type, @@ -565,10 +549,6 @@ GenerationDialogChoice choice, autofill::password_generation::PasswordGenerationType type); -// Log whether there is a conflict with existing credentials when presaving -// a generated password. -void LogGenerationPresaveConflict(GenerationPresaveConflict value); - #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) // Log a save gaia password change event. void LogGaiaPasswordHashChange(GaiaPasswordHashChange event,
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index e40655d..2e0a147 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -283,6 +283,9 @@ // to access Google Docs. // Please see go/cros-demo-mode and go/demo-mode-account-brainstorm. CHROME_OS_DEMO_MODE = 2; + // Authcode will be used by the enterprise-managed Chrome Browser to + // register for policy invalidations. This is requested during enrollment. + CHROME_BROWSER = 3; } // Device type indicates the intended use of the auth code.
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index f9c1cf8..86507b0 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -65,6 +65,10 @@ const base::Feature kUsePreferredIntervalForVideo{ "UsePreferredIntervalForVideo", base::FEATURE_DISABLED_BY_DEFAULT}; +// Whether we should log extra debug information to webrtc native log. +const base::Feature kWebRtcLogCapturePipeline{ + "WebRtcLogCapturePipeline", base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsVizHitTestingDebugEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableVizHitTestDebug); @@ -137,4 +141,8 @@ return base::FeatureList::IsEnabled(kSplitPartiallyOccludedQuads); } +bool ShouldWebRtcLogCapturePipeline() { + return base::FeatureList::IsEnabled(kWebRtcLogCapturePipeline); +} + } // namespace features
diff --git a/components/viz/common/features.h b/components/viz/common/features.h index c66194b..0b38e70 100644 --- a/components/viz/common/features.h +++ b/components/viz/common/features.h
@@ -24,6 +24,7 @@ VIZ_COMMON_EXPORT extern const base::Feature kUsePreferredIntervalForVideo; VIZ_COMMON_EXPORT extern const base::Feature kUseRealBuffersForPageFlipTest; VIZ_COMMON_EXPORT extern const base::Feature kSplitPartiallyOccludedQuads; +VIZ_COMMON_EXPORT extern const base::Feature kWebRtcLogCapturePipeline; VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled(); VIZ_COMMON_EXPORT bool IsUsingSkiaForGLReadback(); @@ -37,6 +38,7 @@ VIZ_COMMON_EXPORT bool IsUsingPreferredIntervalForVideo(); VIZ_COMMON_EXPORT bool ShouldUseRealBuffersForPageFlipTest(); VIZ_COMMON_EXPORT bool ShouldSplitPartiallyOccludedQuads(); +VIZ_COMMON_EXPORT bool ShouldWebRtcLogCapturePipeline(); } // namespace features
diff --git a/components/viz/host/client_frame_sink_video_capturer.cc b/components/viz/host/client_frame_sink_video_capturer.cc index c6d041e..b77d91d2 100644 --- a/components/viz/host/client_frame_sink_video_capturer.cc +++ b/components/viz/host/client_frame_sink_video_capturer.cc
@@ -157,6 +157,12 @@ std::move(callbacks)); } +void ClientFrameSinkVideoCapturer::OnLog(const std::string& message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + consumer_->OnLog(message); +} + void ClientFrameSinkVideoCapturer::OnStopped() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/viz/host/client_frame_sink_video_capturer.h b/components/viz/host/client_frame_sink_video_capturer.h index 409edd4..471756d 100644 --- a/components/viz/host/client_frame_sink_video_capturer.h +++ b/components/viz/host/client_frame_sink_video_capturer.h
@@ -123,7 +123,7 @@ mojo::PendingRemote<mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) final; void OnStopped() final; - + void OnLog(const std::string& message) final; // Establishes connection to FrameSinkVideoCapturer and sends the existing // configuration. void EstablishConnection();
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index e5c65b3..2ed4c9e 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -58,7 +58,8 @@ hit_test_manager_(surface_manager()), restart_id_(params.restart_id), run_all_compositor_stages_before_draw_( - params.run_all_compositor_stages_before_draw) { + params.run_all_compositor_stages_before_draw), + log_capture_pipeline_in_webrtc_(params.log_capture_pipeline_in_webrtc) { surface_manager_.AddObserver(&hit_test_manager_); surface_manager_.AddObserver(this); } @@ -273,7 +274,8 @@ video_capturers_.emplace(std::make_unique<FrameSinkVideoCapturerImpl>( this, std::move(receiver), std::make_unique<media::VideoCaptureOracle>( - true /* enable_auto_throttling */))); + true /* enable_auto_throttling */), + log_capture_pipeline_in_webrtc_)); } void FrameSinkManagerImpl::EvictSurfaces(
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h index 14af688..71c3ff6 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -73,6 +73,7 @@ OutputSurfaceProvider* output_surface_provider = nullptr; uint32_t restart_id = BeginFrameSource::kNotRestartableId; bool run_all_compositor_stages_before_draw = false; + bool log_capture_pipeline_in_webrtc = false; }; explicit FrameSinkManagerImpl(const InitParams& params); // TODO(kylechar): Cleanup tests and remove this constructor. @@ -296,6 +297,9 @@ // Whether display scheduler should wait for all pipeline stages before draw. const bool run_all_compositor_stages_before_draw_; + // Whether capture pipeline should emit log messages to webrtc log. + const bool log_capture_pipeline_in_webrtc_; + // Contains registered frame sink ids, debug labels and synchronization // labels. Map entries will be created when frame sink is registered and // destroyed when frame sink is invalidated.
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 5ad9fc9..24770ba 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" @@ -63,16 +64,21 @@ FrameSinkVideoCapturerImpl::FrameSinkVideoCapturerImpl( FrameSinkVideoCapturerManager* frame_sink_manager, mojo::PendingReceiver<mojom::FrameSinkVideoCapturer> receiver, - std::unique_ptr<media::VideoCaptureOracle> oracle) + std::unique_ptr<media::VideoCaptureOracle> oracle, + bool log_to_webrtc) : frame_sink_manager_(frame_sink_manager), copy_request_source_(base::UnguessableToken::Create()), clock_(base::DefaultTickClock::GetInstance()), oracle_(std::move(oracle)), frame_pool_(kDesignLimitMaxFrames), - feedback_weak_factory_(oracle_.get()) { + feedback_weak_factory_(oracle_.get()), + log_to_webrtc_(log_to_webrtc) { DCHECK(frame_sink_manager_); DCHECK(oracle_); - + if (log_to_webrtc_) { + oracle_->SetLogCallback(base::BindRepeating( + &FrameSinkVideoCapturerImpl::OnLog, base::Unretained(this))); + } // Instantiate a default base::OneShotTimer instance. refresh_frame_retry_timer_.emplace(); @@ -337,6 +343,11 @@ if (source_size != oracle_->source_size()) { oracle_->SetSourceSize(source_size); InvalidateEntireSource(); + if (log_to_webrtc_) { + consumer_->OnLog( + base::StringPrintf("VFC: RefreshSoon() changed active frame size: %s", + source_size.ToString().c_str())); + } } MaybeCaptureFrame(VideoCaptureOracle::kRefreshRequest, gfx::Rect(), @@ -360,6 +371,11 @@ } else { oracle_->SetSourceSize(frame_size); InvalidateEntireSource(); + if (log_to_webrtc_ && consumer_) { + consumer_->OnLog( + base::StringPrintf("VFC: OnFramedamaged() changed frame size: %s", + frame_size.ToString().c_str())); + } } MaybeCaptureFrame(VideoCaptureOracle::kCompositorUpdate, damage_rect, @@ -583,6 +599,30 @@ // If the frame is a resurrected one, just deliver it since it already // contains the most up-to-date capture of the source content. if (can_resurrect_content) { + if (log_to_webrtc_) { + std::string strides = ""; + switch (frame->format()) { + case media::PIXEL_FORMAT_I420: + strides = base::StringPrintf("strideY:%d StrideU:%d StrideV:%d", + frame->stride(VideoFrame::kYPlane), + frame->stride(VideoFrame::kUPlane), + frame->stride(VideoFrame::kVPlane)); + break; + case media::PIXEL_FORMAT_ARGB: + strides = base::StringPrintf("strideRGBA:%d", + frame->stride(VideoFrame::kARGBPlane)); + break; + default: + strides = "strides:???"; + } + consumer_->OnLog(base::StringPrintf( + "VFC: Ressurecting frame format=%s frame_coded_size: %s " + "frame_visible_rect: %s frame_natural_size: %s %s", + VideoPixelFormatToString(frame->format()).c_str(), + frame->coded_size().ToString().c_str(), + frame->visible_rect().ToString().c_str(), + frame->natural_size().ToString().c_str(), strides.c_str())); + } OnFrameReadyForDelivery(capture_frame_number, oracle_frame_number, content_rect, std::move(frame)); return; @@ -613,6 +653,20 @@ // being captured. dirty_rect_ = gfx::Rect(); + if (log_to_webrtc_) { + std::string format = + pixel_format_ == media::PIXEL_FORMAT_I420 ? "I420" : "RGBA_bitmap"; + consumer_->OnLog(base::StringPrintf( + "VFC: Sending CopyRequest: " + "format=%s area:%s " + "scale_from: %s " + "scale_to: %s " + "frame pool utilization: %f", + format.c_str(), request->area().ToString().c_str(), + request->scale_from().ToString().c_str(), + request->scale_to().ToString().c_str(), utilization)); + } + resolved_target_->RequestCopyOfOutput(LocalSurfaceId(), std::move(request)); } @@ -630,6 +684,38 @@ DCHECK(frame); DCHECK(result); + if (log_to_webrtc_ && consumer_) { + std::string format = ""; + std::string strides = ""; + switch (result->format()) { + case CopyOutputResult::Format::I420_PLANES: + format = "I420"; + strides = base::StringPrintf("strideY:%d StrideU:%d StrideV:%d", + frame->stride(VideoFrame::kYPlane), + frame->stride(VideoFrame::kUPlane), + frame->stride(VideoFrame::kVPlane)); + break; + case CopyOutputResult::Format::RGBA_BITMAP: + format = "RGBA_Bitmap"; + strides = base::StringPrintf("strideRGBA:%d", + frame->stride(VideoFrame::kARGBPlane)); + break; + case CopyOutputResult::Format::RGBA_TEXTURE: + format = "RGBA_Texture"; + strides = base::StringPrintf("strideRGBA:%d", + frame->stride(VideoFrame::kARGBPlane)); + break; + } + consumer_->OnLog(base::StringPrintf( + "VFC: got CopyOutputResult: format=%s size:%s frame_coded_size: %s " + "frame_visible_rect: %s frame_natural_size: %s content_rect: %s %s", + format.c_str(), result->size().ToString().c_str(), + frame->coded_size().ToString().c_str(), + frame->visible_rect().ToString().c_str(), + frame->natural_size().ToString().c_str(), + content_rect.ToString().c_str(), strides.c_str())); + } + // Stop() should have canceled any outstanding copy requests. So, by reaching // this point, |consumer_| should be bound. DCHECK(consumer_); @@ -840,6 +926,12 @@ return gfx::Rect(x, y, r - x, b - y); } +void FrameSinkVideoCapturerImpl::OnLog(const std::string& message) { + if (log_to_webrtc_ && consumer_) { + consumer_->OnLog(message); + } +} + FrameSinkVideoCapturerImpl::CapturedFrame::CapturedFrame( int64_t capture_frame_number, OracleFrameNumber oracle_frame_number,
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 5efea91b..36db91ce 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -10,7 +10,7 @@ #include <memory> #include <queue> #include <vector> - +#include "base/callback_forward.h" #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -79,7 +79,8 @@ FrameSinkVideoCapturerImpl( FrameSinkVideoCapturerManager* frame_sink_manager, mojo::PendingReceiver<mojom::FrameSinkVideoCapturer> receiver, - std::unique_ptr<media::VideoCaptureOracle> oracle); + std::unique_ptr<media::VideoCaptureOracle> oracle, + bool log_to_webrtc); ~FrameSinkVideoCapturerImpl() final; @@ -227,6 +228,8 @@ // numbers. static gfx::Rect ExpandRectToI420SubsampleBoundaries(const gfx::Rect& rect); + void OnLog(const std::string& message); + // Owner/Manager of this instance. FrameSinkVideoCapturerManager* const frame_sink_manager_; @@ -335,6 +338,9 @@ // in-flight frame deliveries. base::WeakPtrFactory<media::VideoCaptureOracle> feedback_weak_factory_; + // Enables debug log messages to be sent to webrtc native log. + const bool log_to_webrtc_; + // A weak pointer factory used for cancelling the results from any in-flight // copy output requests. base::WeakPtrFactory<FrameSinkVideoCapturerImpl> capture_weak_factory_{this};
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc index 153ae35..1e99e7b 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -124,6 +124,7 @@ MOCK_METHOD0(OnFrameCapturedMock, void()); MOCK_METHOD0(OnStopped, void()); + MOCK_METHOD1(OnLog, void(const std::string&)); int num_frames_received() const { return frames_.size(); } @@ -379,7 +380,7 @@ true /* enable_auto_throttling */); oracle_ = oracle.get(); capturer_ = std::make_unique<FrameSinkVideoCapturerImpl>( - &frame_sink_manager_, mojo::NullReceiver(), std::move(oracle)); + &frame_sink_manager_, mojo::NullReceiver(), std::move(oracle), false); } void SetUp() override {
diff --git a/components/viz/service/main/viz_compositor_thread_runner_impl.cc b/components/viz/service/main/viz_compositor_thread_runner_impl.cc index 58a329b..e216d82 100644 --- a/components/viz/service/main/viz_compositor_thread_runner_impl.cc +++ b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -198,6 +198,8 @@ init_params.restart_id = params->restart_id; init_params.run_all_compositor_stages_before_draw = run_all_compositor_stages_before_draw; + init_params.log_capture_pipeline_in_webrtc = + features::ShouldWebRtcLogCapturePipeline(); frame_sink_manager_ = std::make_unique<FrameSinkManagerImpl>(init_params); frame_sink_manager_->BindAndSetClient(
diff --git a/content/browser/devtools/devtools_video_consumer.h b/content/browser/devtools/devtools_video_consumer.h index aa86ec8..fe4ab8181 100644 --- a/content/browser/devtools/devtools_video_consumer.h +++ b/content/browser/devtools/devtools_video_consumer.h
@@ -70,6 +70,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) override; void OnStopped() override; + void OnLog(const std::string& /*message*/) override {} // Default min frame size is 1x1, as otherwise, nothing would be captured. static constexpr gfx::Size kDefaultMinFrameSize = gfx::Size(1, 1);
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc index 2630aae..3c93ee9 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device.cc +++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -263,6 +263,21 @@ OnFatalError("Capturer service cannot continue."); } +void FrameSinkVideoCaptureDevice::OnLog(const std::string& message) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (receiver_) { + if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { + receiver_->OnLog(message); + } else { + base::PostTask( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&media::VideoFrameReceiver::OnLog, + base::Unretained(receiver_.get()), message)); + } + } +} + void FrameSinkVideoCaptureDevice::OnTargetChanged( const viz::FrameSinkId& frame_sink_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.h b/content/browser/media/capture/frame_sink_video_capture_device.h index ae98dcb..4508c09 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device.h +++ b/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -82,6 +82,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks> callbacks) final; void OnStopped() final; + void OnLog(const std::string& message) final; // These are called to notify when the capture target has changed or was // permanently lost.
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc index 1d1d45a..99f3db5 100644 --- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc +++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -19,6 +19,7 @@ #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/base/clipboard/clipboard.h" +#include "ui/base/pointer/touch_editing_controller.h" #include "ui/events/event_observer.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/size_conversions.h" @@ -433,11 +434,11 @@ bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD; bool has_selection = !rwhva_->GetSelectedText().empty(); switch (command_id) { - case IDS_APP_CUT: + case ui::TouchEditable::kCut: return editable && readable && has_selection; - case IDS_APP_COPY: + case ui::TouchEditable::kCopy: return readable && has_selection; - case IDS_APP_PASTE: { + case ui::TouchEditable::kPaste: { base::string16 result; ui::Clipboard::GetForCurrentThread()->ReadText( ui::ClipboardBuffer::kCopyPaste, &result); @@ -456,13 +457,13 @@ return; switch (command_id) { - case IDS_APP_CUT: + case ui::TouchEditable::kCut: host_delegate->Cut(); break; - case IDS_APP_COPY: + case ui::TouchEditable::kCopy: host_delegate->Copy(); break; - case IDS_APP_PASTE: + case ui::TouchEditable::kPaste: host_delegate->Paste(); break; default:
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc index 49db289c..6692731 100644 --- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc +++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/touch_selection_controller_client_manager.h" #include "content/public/common/use_zoom_for_dsf_policy.h" #include "ui/base/clipboard/clipboard.h" +#include "ui/base/pointer/touch_editing_controller.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/strings/grit/ui_strings.h" @@ -150,11 +151,11 @@ bool has_selection = !rwhv_->GetSelectedText().empty(); switch (command_id) { - case IDS_APP_CUT: + case ui::TouchEditable::kCut: return editable && readable && has_selection; - case IDS_APP_COPY: + case ui::TouchEditable::kCopy: return readable && has_selection; - case IDS_APP_PASTE: { + case ui::TouchEditable::kPaste: { base::string16 result; ui::Clipboard::GetForCurrentThread()->ReadText( ui::ClipboardBuffer::kCopyPaste, &result); @@ -174,13 +175,13 @@ return; switch (command_id) { - case IDS_APP_CUT: + case ui::TouchEditable::kCut: host_delegate->Cut(); break; - case IDS_APP_COPY: + case ui::TouchEditable::kCopy: host_delegate->Copy(); break; - case IDS_APP_PASTE: + case ui::TouchEditable::kPaste: host_delegate->Paste(); break; default:
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 2b598bc..65a89e6 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
@@ -732,6 +732,7 @@ crbug.com/906742 [ android qualcomm no-passthrough ] conformance2/glsl3/compare-structs-containing-arrays.html [ Failure ] crbug.com/1008535 [ android qualcomm-adreno-(tm)-540 passthrough ] conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html [ Skip ] crbug.com/1000354 [ android qualcomm-adreno-(tm)-540 passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ] +crbug.com/951628 [ android qualcomm-adreno-(tm)-540 passthrough ] conformance/rendering/blending.html [ Failure ] crbug.com/981216 [ android qualcomm-adreno-(tm)-540 ] deqp/functional/gles3/fbocolorbuffer/tex2d_01.html [ RetryOnFailure ] crbug.com/949321 [ android qualcomm ] deqp/functional/gles3/framebufferblit/default_framebuffer_02.html [ RetryOnFailure ] crbug.com/1022410 [ android qualcomm ] conformance2/transform_feedback/switching-objects.html [ RetryOnFailure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 8544745..7d674a9 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -200,6 +200,7 @@ crbug.com/750896 [ win10 nvidia-0x1cb3 d3d9 ] conformance/textures/image_bitmap_from_video/* [ RetryOnFailure ] crbug.com/750896 [ win10 nvidia-0x1cb3 d3d9 ] conformance/textures/video/* [ RetryOnFailure ] crbug.com/829389 [ win10 nvidia-0x1cb3 d3d9 passthrough ] conformance/uniforms/uniform-samplers-test.html [ RetryOnFailure ] +crbug.com/angleproject/4539 [ win10 nvidia-0x1cb3 d3d9 passthrough ] conformance/extensions/oes-texture-half-float-linear.html [ RetryOnFailure ] # Win10 / NVIDIA Quadro P400 failures crbug.com/728670 [ win10 nvidia-0x1cb3 ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ RetryOnFailure ]
diff --git a/fuchsia/runners/cast/cast_runner.cmx b/fuchsia/runners/cast/cast_runner.cmx index 987ad94..43e4234 100644 --- a/fuchsia/runners/cast/cast_runner.cmx +++ b/fuchsia/runners/cast/cast_runner.cmx
@@ -3,7 +3,6 @@ "features": [ "config-data" ], - "$comment": "Not all services are passed to WebEngine, see cast_runner.cc", "services": [ "chromium.cast.ApplicationConfigManager", "fuchsia.accessibility.semantics.SemanticsManager",
diff --git a/ios/chrome/app/application_delegate/app_state.h b/ios/chrome/app/application_delegate/app_state.h index 37aeaa46..86fa7a1f 100644 --- a/ios/chrome/app/application_delegate/app_state.h +++ b/ios/chrome/app/application_delegate/app_state.h
@@ -96,6 +96,9 @@ // -performActionForShortcutItem or -openURL. - (void)launchFromURLHandled:(BOOL)URLHandled; +// Returns the foreground and active scene, if there is one. +- (SceneState*)foregroundActiveScene; + // Returns a list of all connected scenes. - (NSArray<SceneState*>*)connectedScenes;
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm index 100a5d65..8a391afb 100644 --- a/ios/chrome/app/application_delegate/app_state.mm +++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -505,6 +505,16 @@ #pragma mark - Multiwindow-related +- (SceneState*)foregroundActiveScene { + for (SceneState* sceneState in self.connectedScenes) { + if (sceneState.activationLevel == SceneActivationLevelForegroundActive) { + return sceneState; + } + } + + return nil; +} + - (NSArray<SceneState*>*)connectedScenes { if (IsMultiwindowSupported()) { NSMutableArray* sceneStates = [[NSMutableArray alloc] init];
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm index 0e1d2e1..1da1713 100644 --- a/ios/chrome/app/main_application_delegate.mm +++ b/ios/chrome/app/main_application_delegate.mm
@@ -374,6 +374,12 @@ return _appState; } ++ (AppState*)sharedAppState { + return base::mac::ObjCCast<MainApplicationDelegate>( + [[UIApplication sharedApplication] delegate]) + .appState; +} + + (MainController*)sharedMainController { return base::mac::ObjCCast<MainApplicationDelegate>( [[UIApplication sharedApplication] delegate])
diff --git a/ios/chrome/app/main_application_delegate_testing.h b/ios/chrome/app/main_application_delegate_testing.h index 0da219e..42b521f 100644 --- a/ios/chrome/app/main_application_delegate_testing.h +++ b/ios/chrome/app/main_application_delegate_testing.h
@@ -15,6 +15,7 @@ @property(nonatomic, readonly) AppState* appState; + (MainController*)sharedMainController; ++ (AppState*)sharedAppState; @end #endif // IOS_CHROME_APP_MAIN_APPLICATION_DELEGATE_TESTING_H_
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 1677aca..3b3cece8 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -1244,24 +1244,6 @@ @implementation MainController (TestingOnly) -- (BOOL)tabSwitcherActive { - return self.sceneController.isTabSwitcherActive; -} - -- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion - dismissOmnibox:(BOOL)dismissOmnibox { - [self.sceneController dismissModalDialogsWithCompletion:completion - dismissOmnibox:dismissOmnibox]; -} - -- (void)setTabSwitcher:(id<TabSwitcher>)switcher { - [self.sceneController setTabSwitcher:switcher]; -} - -- (id<TabSwitcher>)tabSwitcher { - return self.sceneController.tabSwitcher; -} - - (void)setStartupParametersWithURL:(const GURL&)launchURL { NSString* sourceApplication = @"Fake App"; self.startupParameters = [ChromeAppStartupParameters @@ -1269,9 +1251,4 @@ fromSourceApplication:sourceApplication]; } -// Defined in FirstRunAppInterface for EGTests. -- (void)showFirstRunUI { - [self.sceneController showFirstRunUI]; -} - @end
diff --git a/ios/chrome/app/main_controller_private.h b/ios/chrome/app/main_controller_private.h index 745505d..15502522 100644 --- a/ios/chrome/app/main_controller_private.h +++ b/ios/chrome/app/main_controller_private.h
@@ -25,20 +25,10 @@ // Methods that only exist for tests. @interface MainController (TestingOnly) -// Tab switcher state. -- (BOOL)tabSwitcherActive; - -@property(nonatomic, strong) id<TabSwitcher> tabSwitcher; - // Sets the internal startup state to indicate that the launch was triggered // by an external app opening the given URL. - (void)setStartupParametersWithURL:(const GURL&)launchURL; -// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is -// NO, then call |completion|. -- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion - dismissOmnibox:(BOOL)dismissOmnibox; - @end #endif // IOS_CHROME_APP_MAIN_CONTROLLER_PRIVATE_H_
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn index e1adf9b..639ce62 100644 --- a/ios/chrome/browser/ui/first_run/BUILD.gn +++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -158,6 +158,8 @@ "//ios/chrome/app:app_internal", "//ios/chrome/browser", "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/main:scene", + "//ios/chrome/browser/ui/main:scene_testing", "//ios/chrome/test/app:test_support", ] } @@ -180,6 +182,8 @@ "//ios/chrome/app:app_internal", "//ios/chrome/browser", "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/main:scene", + "//ios/chrome/browser/ui/main:scene_testing", "//ios/chrome/test/app:test_support", "//ios/third_party/earl_grey2:app_framework+link", ]
diff --git a/ios/chrome/browser/ui/first_run/first_run_app_interface.mm b/ios/chrome/browser/ui/first_run/first_run_app_interface.mm index c36755b..9b3e6edb 100644 --- a/ios/chrome/browser/ui/first_run/first_run_app_interface.mm +++ b/ios/chrome/browser/ui/first_run/first_run_app_interface.mm
@@ -12,22 +12,18 @@ #include "ios/chrome/browser/sync/sync_setup_service.h" #include "ios/chrome/browser/sync/sync_setup_service_factory.h" #include "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h" +#import "ios/chrome/browser/ui/main/scene_controller.h" +#import "ios/chrome/browser/ui/main/scene_controller_testing.h" #import "ios/chrome/test/app/chrome_test_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -// TODO(crbug.com/1019942): Develop a better way to show the first run UI that -// doesn't require exposing private API. -@interface MainController (ExposedForTesting) -- (void)showFirstRunUI; -@end - @implementation FirstRunAppInterface + (void)showFirstRunUI { - [chrome_test_util::GetMainController() showFirstRunUI]; + [chrome_test_util::GetForegroundActiveSceneController() showFirstRunUI]; } + (void)setUMACollectionEnabled:(BOOL)enabled {
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index ae656e1..e5eb7eed 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -4,6 +4,12 @@ import("//ios/build/chrome_build.gni") +source_set("scene_testing") { + sources = [ "scene_controller_testing.h" ] + deps = [ "//ios/chrome/browser:utils" ] + libs = [ "UIKit.framework" ] +} + source_set("scene_guts") { sources = [ "scene_controller_guts.h" ] deps = [ @@ -31,6 +37,7 @@ deps = [ ":main", ":scene_guts", + ":scene_testing", "//base", "//components/signin/public/identity_manager", "//components/url_formatter",
diff --git a/ios/chrome/browser/ui/main/scene_controller_guts.h b/ios/chrome/browser/ui/main/scene_controller_guts.h index c99b14bb..bb202da 100644 --- a/ios/chrome/browser/ui/main/scene_controller_guts.h +++ b/ios/chrome/browser/ui/main/scene_controller_guts.h
@@ -17,9 +17,6 @@ @protocol SceneControllerGuts <WebStateListObserving> -- (void)startUpChromeUIPostCrash:(BOOL)isPostCrashLaunch - needRestoration:(BOOL)needsRestoration; - - (void)dismissModalsAndOpenSelectedTabInMode: (ApplicationModeForTabOpening)targetMode withUrlLoadParams: @@ -27,17 +24,11 @@ dismissOmnibox:(BOOL)dismissOmnibox completion:(ProceduralBlock)completion; -// Testing only. -- (void)showFirstRunUI; -- (void)setTabSwitcher:(id<TabSwitcher>)switcher; -- (id<TabSwitcher>)tabSwitcher; -- (BOOL)isTabSwitcherActive; - -- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion - dismissOmnibox:(BOOL)dismissOmnibox; - #pragma mark - iOS 12 compat +- (void)startUpChromeUIPostCrash:(BOOL)isPostCrashLaunch + needRestoration:(BOOL)needsRestoration; + // Method called on SceneController when the scene disconnects. Exposed here for // iOS 12 compatibility. - (void)teardownUI;
diff --git a/ios/chrome/browser/ui/main/scene_controller_testing.h b/ios/chrome/browser/ui/main/scene_controller_testing.h new file mode 100644 index 0000000..e8522db --- /dev/null +++ b/ios/chrome/browser/ui/main/scene_controller_testing.h
@@ -0,0 +1,27 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_TESTING_H_ +#define IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_TESTING_H_ + +#import "ios/chrome/browser/procedural_block_types.h" + +@protocol TabSwitcher; + +// Methods exposed for testing. This is terrible and should be rewritten. +@interface SceneController () + +- (void)showFirstRunUI; +- (void)setTabSwitcher:(id<TabSwitcher>)switcher; +- (id<TabSwitcher>)tabSwitcher; +- (BOOL)isTabSwitcherActive; + +// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is +// NO, then call |completion|. +- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion + dismissOmnibox:(BOOL)dismissOmnibox; + +@end + +#endif // IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_TESTING_H_
diff --git a/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm b/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm index 09e17d1..e2abcd2 100644 --- a/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm +++ b/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm
@@ -33,41 +33,44 @@ - (void)prepareCredentialListForServiceIdentifiers: (NSArray<ASCredentialServiceIdentifier*>*)serviceIdentifiers { - self.listCoordinator = [[CredentialListCoordinator alloc] - initWithBaseViewController:self - context:self.extensionContext - serviceIdentifiers:serviceIdentifiers]; - [self.listCoordinator start]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - // TODO(crbug.com/1045455): Remove, this is for testing purpose only. [self reauthenticateIfNeededWithCompletionHandler:^( ReauthenticationResult result) { - // TODO(crbug.com/1045455): Check result before cancelling. - [self.extensionContext - cancelRequestWithError: - [[NSError alloc] - initWithDomain:ASExtensionErrorDomain - code:ASExtensionErrorCode::ASExtensionErrorCodeFailed - userInfo:nil]]; + if (result != ReauthenticationResult::kFailure) { + self.listCoordinator = [[CredentialListCoordinator alloc] + initWithBaseViewController:self + context:self.extensionContext + serviceIdentifiers:serviceIdentifiers]; + [self.listCoordinator start]; + + } else { + [self.extensionContext + cancelRequestWithError: + [[NSError alloc] initWithDomain:ASExtensionErrorDomain + code:ASExtensionErrorCode:: + ASExtensionErrorCodeFailed + userInfo:nil]]; + } }]; } #pragma mark - Properties - (ReauthenticationHandler*)reauthenticationHandler { - if (!self.reauthenticationModule) { - self.reauthenticationModule = [[ReauthenticationModule alloc] - initWithSuccessfulReauthTimeAccessor:self]; - self.reauthenticationHandler = [[ReauthenticationHandler alloc] + if (!_reauthenticationHandler) { + _reauthenticationHandler = [[ReauthenticationHandler alloc] initWithReauthenticationModule:self.reauthenticationModule]; } return _reauthenticationHandler; } +- (ReauthenticationModule*)reauthenticationModule { + if (!_reauthenticationModule) { + _reauthenticationModule = [[ReauthenticationModule alloc] + initWithSuccessfulReauthTimeAccessor:self]; + } + return _reauthenticationModule; +} + #pragma mark - Private - (void)reauthenticateIfNeededWithCompletionHandler:
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index 144bb626..0289675 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -72,6 +72,8 @@ "//ios/chrome/browser/ui/browser_view", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/main", + "//ios/chrome/browser/ui/main:scene", + "//ios/chrome/browser/ui/main:scene_testing", "//ios/chrome/browser/ui/settings", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/password",
diff --git a/ios/chrome/test/app/chrome_test_util.h b/ios/chrome/test/app/chrome_test_util.h index ca860a4..ff0ccb9 100644 --- a/ios/chrome/test/app/chrome_test_util.h +++ b/ios/chrome/test/app/chrome_test_util.h
@@ -14,6 +14,8 @@ class ChromeBrowserState; @class MainController; @class NewTabPageController; +@class SceneController; +@class SceneState; @class UIViewController; namespace chrome_test_util { @@ -21,6 +23,12 @@ // Returns the main controller. MainController* GetMainController(); +// Returns the foreground, active scene. +SceneState* GetForegroundActiveScene(); + +// Returns the foreground, active scene controller. +SceneController* GetForegroundActiveSceneController(); + // Returns the current, non-incognito ChromeBrowserState. ChromeBrowserState* GetOriginalBrowserState();
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm index f41e916..7223e45 100644 --- a/ios/chrome/test/app/chrome_test_util.mm +++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -9,6 +9,7 @@ #import "base/test/ios/wait_util.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" +#import "ios/chrome/app/application_delegate/app_state.h" #import "ios/chrome/app/application_delegate/metrics_mediator.h" #import "ios/chrome/app/application_delegate/metrics_mediator_testing.h" #import "ios/chrome/app/chrome_overlay_window.h" @@ -24,6 +25,9 @@ #import "ios/chrome/browser/metrics/previous_session_info_private.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h" +#import "ios/chrome/browser/ui/main/scene_controller.h" +#import "ios/chrome/browser/ui/main/scene_controller_testing.h" +#import "ios/chrome/browser/ui/main/scene_state.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/test/app/tab_test_util.h" #import "ios/web/public/navigation/navigation_context.h" @@ -78,6 +82,15 @@ return [MainApplicationDelegate sharedMainController]; } +SceneState* GetForegroundActiveScene() { + return MainApplicationDelegate.sharedAppState.foregroundActiveScene; +} + +SceneController* GetForegroundActiveSceneController() { + return MainApplicationDelegate.sharedAppState.foregroundActiveScene + .controller; +} + ChromeBrowserState* GetOriginalBrowserState() { return GetBrowserState(false); } @@ -132,8 +145,8 @@ } void ClearPresentedState() { - [GetMainController() dismissModalDialogsWithCompletion:nil - dismissOmnibox:YES]; + [GetForegroundActiveSceneController() dismissModalDialogsWithCompletion:nil + dismissOmnibox:YES]; } void SetBooleanLocalStatePref(const char* pref_name, bool value) {
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm index 6576a78..c56d18cc 100644 --- a/ios/chrome/test/app/tab_test_util.mm +++ b/ios/chrome/test/app/tab_test_util.mm
@@ -17,6 +17,8 @@ #import "ios/chrome/browser/tabs/tab_title_util.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" +#import "ios/chrome/browser/ui/main/scene_controller.h" +#import "ios/chrome/browser/ui/main/scene_controller_testing.h" #import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" @@ -57,12 +59,12 @@ void OpenNewTab() { @autoreleasepool { // Make sure that all internals are deallocated. OpenNewTabCommand* command = [OpenNewTabCommand command]; - if (GetMainController().tabSwitcherActive) { + if (GetForegroundActiveSceneController().isTabSwitcherActive) { // The TabGrid is currently presented. Browser* browser = - GetMainController().interfaceProvider.mainInterface.browser; + GetForegroundActiveScene().interfaceProvider.mainInterface.browser; UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); - [GetMainController().tabSwitcher + [GetForegroundActiveSceneController().tabSwitcher dismissWithNewTabAnimationToBrowser:browser withUrlLoadParams:params atIndex:INT_MAX]; @@ -84,12 +86,12 @@ void OpenNewIncognitoTab() { @autoreleasepool { // Make sure that all internals are deallocated. OpenNewTabCommand* command = [OpenNewTabCommand incognitoTabCommand]; - if (GetMainController().tabSwitcherActive) { + if (GetForegroundActiveSceneController().isTabSwitcherActive) { // The TabGrid is currently presented. - Browser* browser = - GetMainController().interfaceProvider.incognitoInterface.browser; + Browser* browser = GetForegroundActiveScene() + .interfaceProvider.incognitoInterface.browser; UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); - [GetMainController().tabSwitcher + [GetForegroundActiveSceneController().tabSwitcher dismissWithNewTabAnimationToBrowser:browser withUrlLoadParams:params atIndex:INT_MAX]; @@ -147,7 +149,7 @@ } NSUInteger GetIndexOfActiveNormalTab() { - TabModel* model = chrome_test_util::GetMainController() + TabModel* model = chrome_test_util::GetForegroundActiveSceneController() .interfaceProvider.mainInterface.tabModel; return model.webStateList->active_index(); } @@ -158,11 +160,12 @@ void CloseAllTabs() { if (GetIncognitoTabCount()) { - [GetMainController() + [GetForegroundActiveSceneController() .interfaceProvider.incognitoInterface.tabModel closeAllTabs]; } if (GetMainTabCount()) { - [GetMainController().interfaceProvider.mainInterface.tabModel closeAllTabs]; + [GetForegroundActiveScene() + .interfaceProvider.mainInterface.tabModel closeAllTabs]; } }
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 45276a9..9bc2f49 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/buildflag_header.gni") import("//build/config/ios/ios_sdk.gni") import("//build/config/ios/rules.gni") import("//build/config/locales.gni") @@ -15,15 +14,6 @@ import("//testing/test.gni") import("//tools/grit/repack.gni") -buildflag_header("web_view_buildflags") { - header = "cwv_web_view_buildflags.h" - - flags = [ - "IOS_WEB_VIEW_ENABLE_SYNC=$ios_web_view_enable_sync", - "IOS_WEB_VIEW_ENABLE_AUTOFILL=$ios_web_view_enable_autofill", - ] -} - group("all_tests") { testonly = true deps = [ @@ -44,22 +34,40 @@ # These are defined as vars so they can be shared with different targets below. ios_web_view_public_headers = [ + "public/cwv_autofill_controller.h", + "public/cwv_autofill_controller_delegate.h", + "public/cwv_autofill_data_manager.h", + "public/cwv_autofill_data_manager_observer.h", + "public/cwv_autofill_form.h", + "public/cwv_autofill_profile.h", + "public/cwv_autofill_suggestion.h", "public/cwv_back_forward_list.h", "public/cwv_back_forward_list_item.h", + "public/cwv_credit_card.h", + "public/cwv_credit_card_expiration_fixer.h", + "public/cwv_credit_card_name_fixer.h", + "public/cwv_credit_card_saver.h", + "public/cwv_credit_card_verifier.h", "public/cwv_download_task.h", "public/cwv_export.h", "public/cwv_favicon.h", "public/cwv_flags.h", "public/cwv_html_element.h", + "public/cwv_identity.h", "public/cwv_navigation_action.h", "public/cwv_navigation_delegate.h", "public/cwv_navigation_type.h", + "public/cwv_password.h", "public/cwv_preferences.h", + "public/cwv_preferences_autofill.h", "public/cwv_preview_element_info.h", "public/cwv_script_command.h", "public/cwv_scroll_view.h", "public/cwv_scroll_view_delegate.h", "public/cwv_ssl_status.h", + "public/cwv_sync_controller.h", + "public/cwv_sync_controller_data_source.h", + "public/cwv_sync_controller_delegate.h", "public/cwv_translation_controller.h", "public/cwv_translation_controller_delegate.h", "public/cwv_translation_language.h", @@ -68,37 +76,11 @@ "public/cwv_user_content_controller.h", "public/cwv_user_script.h", "public/cwv_web_view.h", + "public/cwv_web_view_autofill.h", "public/cwv_web_view_configuration.h", + "public/cwv_web_view_configuration_autofill.h", + "public/cwv_web_view_configuration_sync.h", ] -if (ios_web_view_enable_sync) { - ios_web_view_public_headers += [ - "public/cwv_identity.h", - "public/cwv_sync_controller.h", - "public/cwv_sync_controller_data_source.h", - "public/cwv_sync_controller_delegate.h", - "public/cwv_web_view_configuration_sync.h", - ] -} -if (ios_web_view_enable_autofill) { - ios_web_view_public_headers += [ - "public/cwv_autofill_controller.h", - "public/cwv_autofill_controller_delegate.h", - "public/cwv_autofill_data_manager.h", - "public/cwv_autofill_data_manager_observer.h", - "public/cwv_autofill_form.h", - "public/cwv_autofill_profile.h", - "public/cwv_autofill_suggestion.h", - "public/cwv_credit_card.h", - "public/cwv_credit_card_expiration_fixer.h", - "public/cwv_credit_card_name_fixer.h", - "public/cwv_credit_card_saver.h", - "public/cwv_credit_card_verifier.h", - "public/cwv_password.h", - "public/cwv_preferences_autofill.h", - "public/cwv_web_view_autofill.h", - "public/cwv_web_view_configuration_autofill.h", - ] -} source_set("web_view_sources") { sources = ios_web_view_public_headers @@ -107,6 +89,27 @@ "internal/app/application_context.mm", "internal/app/web_view_io_thread.h", "internal/app/web_view_io_thread.mm", + "internal/autofill/cwv_autofill_client_ios_bridge.h", + "internal/autofill/cwv_autofill_controller.mm", + "internal/autofill/cwv_autofill_controller_internal.h", + "internal/autofill/cwv_autofill_data_manager.mm", + "internal/autofill/cwv_autofill_data_manager_internal.h", + "internal/autofill/cwv_autofill_form.mm", + "internal/autofill/cwv_autofill_form_internal.h", + "internal/autofill/cwv_autofill_profile.mm", + "internal/autofill/cwv_autofill_profile_internal.h", + "internal/autofill/cwv_autofill_suggestion.mm", + "internal/autofill/cwv_autofill_suggestion_internal.h", + "internal/autofill/cwv_credit_card.mm", + "internal/autofill/cwv_credit_card_expiration_fixer.mm", + "internal/autofill/cwv_credit_card_expiration_fixer_internal.h", + "internal/autofill/cwv_credit_card_internal.h", + "internal/autofill/cwv_credit_card_name_fixer.mm", + "internal/autofill/cwv_credit_card_name_fixer_internal.h", + "internal/autofill/cwv_credit_card_saver.mm", + "internal/autofill/cwv_credit_card_saver_internal.h", + "internal/autofill/cwv_credit_card_verifier.mm", + "internal/autofill/cwv_credit_card_verifier_internal.h", "internal/autofill/web_view_autocomplete_history_manager_factory.h", "internal/autofill/web_view_autocomplete_history_manager_factory.mm", "internal/autofill/web_view_autofill_client_ios.h", @@ -160,6 +163,10 @@ "internal/language/web_view_language_model_manager_factory.mm", "internal/language/web_view_url_language_histogram_factory.h", "internal/language/web_view_url_language_histogram_factory.mm", + "internal/passwords/cwv_password.mm", + "internal/passwords/cwv_password_controller.h", + "internal/passwords/cwv_password_controller.mm", + "internal/passwords/cwv_password_internal.h", "internal/passwords/web_view_password_feature_manager.h", "internal/passwords/web_view_password_feature_manager.mm", "internal/passwords/web_view_password_manager_client.h", @@ -172,6 +179,7 @@ "internal/passwords/web_view_password_store_factory.mm", "internal/pref_names.h", "internal/pref_names.mm", + "internal/signin/cwv_identity.mm", "internal/signin/ios_web_view_signin_client.h", "internal/signin/ios_web_view_signin_client.mm", "internal/signin/web_view_device_accounts_provider_impl.h", @@ -182,6 +190,8 @@ "internal/signin/web_view_signin_client_factory.mm", "internal/signin/web_view_signin_error_controller_factory.h", "internal/signin/web_view_signin_error_controller_factory.mm", + "internal/sync/cwv_sync_controller.mm", + "internal/sync/cwv_sync_controller_internal.h", "internal/sync/web_view_device_info_sync_service_factory.h", "internal/sync/web_view_device_info_sync_service_factory.mm", "internal/sync/web_view_gcm_profile_service_factory.h", @@ -233,46 +243,9 @@ "internal/webdata_services/web_view_web_data_service_wrapper_factory.h", "internal/webdata_services/web_view_web_data_service_wrapper_factory.mm", ] - if (ios_web_view_enable_sync) { - sources += [ - "internal/signin/cwv_identity.mm", - "internal/sync/cwv_sync_controller.mm", - "internal/sync/cwv_sync_controller_internal.h", - ] - } - if (ios_web_view_enable_autofill) { - sources += [ - "internal/autofill/cwv_autofill_client_ios_bridge.h", - "internal/autofill/cwv_autofill_controller.mm", - "internal/autofill/cwv_autofill_controller_internal.h", - "internal/autofill/cwv_autofill_data_manager.mm", - "internal/autofill/cwv_autofill_data_manager_internal.h", - "internal/autofill/cwv_autofill_form.mm", - "internal/autofill/cwv_autofill_form_internal.h", - "internal/autofill/cwv_autofill_profile.mm", - "internal/autofill/cwv_autofill_profile_internal.h", - "internal/autofill/cwv_autofill_suggestion.mm", - "internal/autofill/cwv_autofill_suggestion_internal.h", - "internal/autofill/cwv_credit_card.mm", - "internal/autofill/cwv_credit_card_expiration_fixer.mm", - "internal/autofill/cwv_credit_card_expiration_fixer_internal.h", - "internal/autofill/cwv_credit_card_internal.h", - "internal/autofill/cwv_credit_card_name_fixer.mm", - "internal/autofill/cwv_credit_card_name_fixer_internal.h", - "internal/autofill/cwv_credit_card_saver.mm", - "internal/autofill/cwv_credit_card_saver_internal.h", - "internal/autofill/cwv_credit_card_verifier.mm", - "internal/autofill/cwv_credit_card_verifier_internal.h", - "internal/passwords/cwv_password.mm", - "internal/passwords/cwv_password_controller.h", - "internal/passwords/cwv_password_controller.mm", - "internal/passwords/cwv_password_internal.h", - ] - } public_deps = [ ":web_view_all_frames", - ":web_view_buildflags", ":web_view_main_frame", ":web_view_resources", "//base", @@ -349,12 +322,7 @@ ] } -# Generate the umbrella header to exclude headers for disabled features. -# This is preferable to guarding header imports using flags defined in -# :web_view_buildflags because: -# 1. Confusing to see headers for unsupported features in umbrella header. -# 2. A need to include cwv_web_view_buildflags.h as part of public headers and -# any headers it itself includes, despite not being part of the public API. +# Generate the umbrella header. action("web_view_umbrella_header") { script = "//build/config/ios/generate_umbrella_header.py" @@ -555,10 +523,8 @@ deps = [ ":repack_locales", ":repack_resources", + ":repack_scalable_resources", ] - if (ios_web_view_enable_autofill) { - deps += [ ":repack_scalable_resources" ] - } } if (additional_toolchains == [] || current_toolchain == default_toolchain) {
diff --git a/ios/web_view/features.gni b/ios/web_view/features.gni index 7db5fe0c..6d731811 100644 --- a/ios/web_view/features.gni +++ b/ios/web_view/features.gni
@@ -6,12 +6,6 @@ # Controls if cronet is included. ios_web_view_include_cronet = true - # Controls if sync APIs are exposed. - ios_web_view_enable_sync = true - - # Controls if autofill APIs are exposed. - ios_web_view_enable_autofill = true - # Controls the output name of the built framework. ios_web_view_output_name = "ChromeWebView" }
diff --git a/ios/web_view/internal/app/application_context.mm b/ios/web_view/internal/app/application_context.mm index eaefa7d..f8d251d9 100644 --- a/ios/web_view/internal/app/application_context.mm +++ b/ios/web_view/internal/app/application_context.mm
@@ -15,11 +15,11 @@ #include "components/prefs/pref_service.h" #include "components/prefs/pref_service_factory.h" #include "components/proxy_config/pref_proxy_config_tracker_impl.h" +#include "components/signin/public/identity_manager/identity_manager.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/variations/net/variations_http_headers.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/public/thread/web_thread.h" -#include "ios/web_view/cwv_web_view_buildflags.h" #include "ios/web_view/internal/app/web_view_io_thread.h" #import "ios/web_view/internal/cwv_flags_internal.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -31,10 +31,6 @@ #include "services/network/public/mojom/network_context.mojom.h" #include "ui/base/l10n/l10n_util_mac.h" -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) -#include "components/signin/public/identity_manager/identity_manager.h" -#endif - #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -102,9 +98,7 @@ scoped_refptr<PrefRegistrySimple> pref_registry(new PrefRegistrySimple); flags_ui::PrefServiceFlagsStorage::RegisterPrefs(pref_registry.get()); PrefProxyConfigTrackerImpl::RegisterPrefs(pref_registry.get()); -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) signin::IdentityManager::RegisterLocalStatePrefs(pref_registry.get()); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) base::FilePath local_state_path; base::PathService::Get(base::DIR_APP_DATA, &local_state_path);
diff --git a/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h b/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h index 63d92ea..5cfcad1 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h +++ b/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h
@@ -47,6 +47,20 @@ callback:(autofill::AutofillClient:: UploadSaveCardPromptCallback)callback; +// Bridge For AutofillClient's method |ConfirmAccountNameFixFlow|. +- (void) + confirmCreditCardAccountName:(const base::string16&)name + callback: + (base::OnceCallback<void(const base::string16&)>) + callback; + +// Bridge For AutofillClient's method |ConfirmExpirationDateFixFlow|. +- (void)confirmCreditCardExpirationWithCard:(const autofill::CreditCard&)card + callback: + (base::OnceCallback<void( + const base::string16&, + const base::string16&)>)callback; + // Bridge for AutofillClient's method |CreditCardUploadCompleted|. - (void)handleCreditCardUploadCompleted:(BOOL)cardSaved;
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm index b76f3af..9cca322a 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -37,7 +37,9 @@ #import "ios/web_view/internal/autofill/cwv_autofill_form_internal.h" #import "ios/web_view/internal/autofill/cwv_autofill_profile_internal.h" #import "ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h" +#import "ios/web_view/internal/autofill/cwv_credit_card_expiration_fixer_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_internal.h" +#import "ios/web_view/internal/autofill/cwv_credit_card_name_fixer_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_saver_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_verifier_internal.h" #include "ios/web_view/internal/autofill/web_view_autocomplete_history_manager_factory.h" @@ -425,6 +427,39 @@ } - (void) + confirmCreditCardAccountName:(const base::string16&)name + callback: + (base::OnceCallback<void(const base::string16&)>) + callback { + if (![_delegate respondsToSelector:@selector(autofillController: + confirmCreditCardNameWithFixer:)]) { + return; + } + + CWVCreditCardNameFixer* fixer = [[CWVCreditCardNameFixer alloc] + initWithName:base::SysUTF16ToNSString(name) + callback:std::move(callback)]; + [_delegate autofillController:self confirmCreditCardNameWithFixer:fixer]; +} + +- (void)confirmCreditCardExpirationWithCard:(const autofill::CreditCard&)card + callback: + (base::OnceCallback<void( + const base::string16&, + const base::string16&)>)callback { + if (![_delegate respondsToSelector:@selector + (autofillController:confirmCreditCardExpirationWithFixer:)]) { + return; + } + + CWVCreditCardExpirationFixer* fixer = [[CWVCreditCardExpirationFixer alloc] + initWithCreditCard:card + callback:std::move(callback)]; + [_delegate autofillController:self + confirmCreditCardExpirationWithFixer:fixer]; +} + +- (void) confirmSaveCreditCardToCloud:(const autofill::CreditCard&)creditCard legalMessageLines:(autofill::LegalMessageLines)legalMessageLines saveCreditCardOptions:
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm index 3f26a66..0061630 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -181,14 +181,22 @@ void WebViewAutofillClientIOS::ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) { - NOTIMPLEMENTED(); + base::Optional<AccountInfo> primary_account_info = + identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken( + identity_manager_->GetPrimaryAccountInfo()); + base::string16 account_name = + primary_account_info ? base::UTF8ToUTF16(primary_account_info->full_name) + : base::string16(); + [bridge_ confirmCreditCardAccountName:account_name + callback:std::move(callback)]; } void WebViewAutofillClientIOS::ConfirmExpirationDateFixFlow( const CreditCard& card, base::OnceCallback<void(const base::string16&, const base::string16&)> callback) { - NOTIMPLEMENTED(); + [bridge_ confirmCreditCardExpirationWithCard:card + callback:std::move(callback)]; } void WebViewAutofillClientIOS::ConfirmSaveCreditCardToCloud(
diff --git a/ios/web_view/internal/cwv_preferences.mm b/ios/web_view/internal/cwv_preferences.mm index 85ad5e4..4d5117ea 100644 --- a/ios/web_view/internal/cwv_preferences.mm +++ b/ios/web_view/internal/cwv_preferences.mm
@@ -4,16 +4,12 @@ #import "ios/web_view/internal/cwv_preferences_internal.h" +#include "components/autofill/core/common/autofill_prefs.h" #include "components/language/core/browser/pref_names.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" #include "components/translate/core/browser/translate_pref_names.h" #include "components/translate/core/browser/translate_prefs.h" -#include "ios/web_view/cwv_web_view_buildflags.h" - -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) -#include "components/autofill/core/common/autofill_prefs.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -48,7 +44,6 @@ translatePrefs.ResetToDefaults(); } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #pragma mark - Autofill - (void)setProfileAutofillEnabled:(BOOL)enabled { @@ -77,6 +72,4 @@ password_manager::prefs::kCredentialsEnableService); } -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) - @end
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm index 5f1292c..f67bda60 100644 --- a/ios/web_view/internal/cwv_web_view.mm +++ b/ios/web_view/internal/cwv_web_view.mm
@@ -37,7 +37,6 @@ #import "ios/web/public/web_state_delegate_bridge.h" #import "ios/web/public/web_state_observer_bridge.h" #import "ios/web/public/web_view_only/wk_web_view_configuration_util.h" -#include "ios/web_view/cwv_web_view_buildflags.h" #import "ios/web_view/internal/autofill/cwv_autofill_controller_internal.h" #import "ios/web_view/internal/cwv_back_forward_list_internal.h" #import "ios/web_view/internal/cwv_favicon_internal.h" @@ -137,9 +136,7 @@ @property(nonatomic, readwrite) NSURL* visibleURL; @property(nonatomic, readwrite) NSString* visibleLocationString; @property(nonatomic, readwrite) CWVSSLStatus* visibleSSLStatus; -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) @property(nonatomic, readonly) CWVAutofillController* autofillController; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) // Updates the availability of the back/forward navigation properties exposed // through |canGoBack| and |canGoForward|, and also updates |backForwardList|. @@ -148,10 +145,8 @@ - (void)updateCurrentURLs; // Updates |title| property. - (void)updateTitle; -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) // Returns a new CWVAutofillController created from |_webState|. - (CWVAutofillController*)newAutofillController; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) // Returns a new CWVTranslationController created from |_webState|. - (CWVTranslationController*)newTranslationController; // Updates |_webState| visiblity. @@ -166,9 +161,7 @@ @implementation CWVWebView -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) @synthesize autofillController = _autofillController; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) @synthesize backForwardList = _backForwardList; @synthesize canGoBack = _canGoBack; @synthesize canGoForward = _canGoForward; @@ -628,7 +621,6 @@ initWithTranslateClient:translateClient]; } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #pragma mark - Autofill - (CWVAutofillController*)autofillController { @@ -660,8 +652,6 @@ passwordController:passwordController]; } -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) - #pragma mark - Preserving and Restoring State - (void)encodeRestorableStateWithCoder:(NSCoder*)coder { @@ -804,14 +794,12 @@ _translationController.delegate = delegate; } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) // Recreate and restore the delegate only if previously lazily loaded. if (_autofillController) { id<CWVAutofillControllerDelegate> delegate = _autofillController.delegate; _autofillController = [self newAutofillController]; _autofillController.delegate = delegate; } -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) [self addInternalWebViewAsSubview];
diff --git a/ios/web_view/internal/cwv_web_view_configuration.mm b/ios/web_view/internal/cwv_web_view_configuration.mm index 0fa5186..e199882 100644 --- a/ios/web_view/internal/cwv_web_view_configuration.mm +++ b/ios/web_view/internal/cwv_web_view_configuration.mm
@@ -12,7 +12,6 @@ #include "components/keyed_service/core/service_access_type.h" #include "components/password_manager/core/browser/password_store_default.h" #include "components/sync/driver/sync_service.h" -#include "ios/web_view/cwv_web_view_buildflags.h" #include "ios/web_view/internal/app/application_context.h" #import "ios/web_view/internal/autofill/cwv_autofill_data_manager_internal.h" #include "ios/web_view/internal/autofill/web_view_personal_data_manager_factory.h" @@ -40,18 +39,14 @@ NSHashTable* _webViews; } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) // This web view configuration's autofill data manager. // nil if CWVWebViewConfiguration is created with +incognitoConfiguration. @property(nonatomic, readonly, nullable) CWVAutofillDataManager* autofillDataManager; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) // This web view configuration's sync controller. // nil if CWVWebViewConfiguration is created with +incognitoConfiguration. @property(nonatomic, readonly, nullable) CWVSyncController* syncController; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) // Initializes configuration with the specified browser state mode. - (instancetype)initWithBrowserState: @@ -61,13 +56,9 @@ @implementation CWVWebViewConfiguration -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) @synthesize autofillDataManager = _autofillDataManager; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) @synthesize preferences = _preferences; -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) @synthesize syncController = _syncController; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) @synthesize userContentController = _userContentController; namespace { @@ -131,8 +122,8 @@ return self; } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #pragma mark - Autofill + - (CWVAutofillDataManager*)autofillDataManager { if (!_autofillDataManager && self.persistent) { autofill::PersonalDataManager* personalDataManager = @@ -147,10 +138,9 @@ } return _autofillDataManager; } -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) #pragma mark - Sync + - (CWVSyncController*)syncController { if (!_syncController && self.persistent) { syncer::SyncService* syncService = @@ -183,7 +173,6 @@ } return _syncController; } -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) #pragma mark - Public Methods @@ -205,9 +194,7 @@ for (CWVWebView* webView in _webViews) { [webView shutDown]; } -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) [_syncController shutDown]; -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) _browserState.reset(); }
diff --git a/ios/web_view/internal/web_view_browser_state.mm b/ios/web_view/internal/web_view_browser_state.mm index 26d0d55..9cc85c09 100644 --- a/ios/web_view/internal/web_view_browser_state.mm +++ b/ios/web_view/internal/web_view_browser_state.mm
@@ -31,7 +31,6 @@ #include "components/translate/core/browser/translate_prefs.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/public/thread/web_thread.h" -#include "ios/web_view/cwv_web_view_buildflags.h" #include "ios/web_view/internal/app/application_context.h" #import "ios/web_view/internal/autofill/web_view_autofill_log_router_factory.h" #include "ios/web_view/internal/autofill/web_view_personal_data_manager_factory.h" @@ -109,9 +108,7 @@ base::ThreadRestrictions::SetIOAllowed(wasIOAllowed); -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) ActiveStateManager::FromBrowserState(this)->SetActive(true); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) BrowserStateDependencyManager::GetInstance()->CreateBrowserStateServices( this); @@ -121,9 +118,7 @@ BrowserStateDependencyManager::GetInstance()->DestroyBrowserStateServices( this); -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) ActiveStateManager::FromBrowserState(this)->SetActive(false); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) base::PostTask(FROM_HERE, {web::WebThread::IO}, base::BindOnce(&WebViewURLRequestContextGetter::ShutDown, @@ -170,33 +165,22 @@ true); language::LanguagePrefs::RegisterProfilePrefs(pref_registry); translate::TranslatePrefs::RegisterProfilePrefs(pref_registry); - -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) autofill::prefs::RegisterProfilePrefs(pref_registry); password_manager::PasswordManager::RegisterProfilePrefs(pref_registry); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) - -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(pref_registry); syncer::SyncPrefs::RegisterProfilePrefs(pref_registry); syncer::DeviceInfoPrefs::RegisterProfilePrefs(pref_registry); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) // Instantiate all factories to setup dependency graph for pref registration. WebViewLanguageModelManagerFactory::GetInstance(); WebViewTranslateRankerFactory::GetInstance(); WebViewUrlLanguageHistogramFactory::GetInstance(); WebViewTranslateAcceptLanguagesFactory::GetInstance(); - -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) autofill::WebViewAutofillLogRouterFactory::GetInstance(); WebViewPersonalDataManagerFactory::GetInstance(); WebViewWebDataServiceWrapperFactory::GetInstance(); WebViewPasswordManagerLogRouterFactory::GetInstance(); WebViewPasswordStoreFactory::GetInstance(); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) - -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) WebViewCookieSettingsFactory::GetInstance(); WebViewHostContentSettingsMapFactory::GetInstance(); WebViewSigninClientFactory::GetInstance(); @@ -206,7 +190,6 @@ WebViewProfileInvalidationProviderFactory::GetInstance(); WebViewProfileSyncServiceFactory::GetInstance(); WebViewModelTypeStoreServiceFactory::GetInstance(); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) BrowserStateDependencyManager::GetInstance() ->RegisterBrowserStatePrefsForServices(pref_registry);
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index 521b938..20a40249 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -12,7 +12,6 @@ #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/content_settings/core/common/content_settings_pattern.h" -#include "ios/web_view/cwv_web_view_buildflags.h" #include "ios/web_view/internal/app/application_context.h" #import "ios/web_view/internal/cwv_flags_internal.h" #import "ios/web_view/internal/cwv_web_view_configuration_internal.h" @@ -49,7 +48,6 @@ ApplicationContext::GetInstance()->PreCreateThreads(); -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); std::string enable_features = base::JoinString( {autofill::features::kAutofillUpstream.name, @@ -61,16 +59,13 @@ /*enable_features=*/enable_features, /*disable_features=*/disabled_features); base::FeatureList::SetInstance(std::move(feature_list)); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) } void WebViewWebMainParts::PreMainMessageLoopRun() { WebViewTranslateService::GetInstance()->Initialize(); -#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes( /*schemes=*/nullptr, 0); -#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_SYNC) } void WebViewWebMainParts::PostMainMessageLoopRun() {
diff --git a/ios/web_view/public/cwv_autofill_controller_delegate.h b/ios/web_view/public/cwv_autofill_controller_delegate.h index e309607..da53b219 100644 --- a/ios/web_view/public/cwv_autofill_controller_delegate.h +++ b/ios/web_view/public/cwv_autofill_controller_delegate.h
@@ -14,6 +14,8 @@ @class CWVAutofillFormSuggestion; @class CWVAutofillProfile; @class CWVCreditCard; +@class CWVCreditCardExpirationFixer; +@class CWVCreditCardNameFixer; @class CWVCreditCardSaver; @class CWVCreditCardVerifier; @class CWVPassword; @@ -101,6 +103,22 @@ - (void)autofillController:(CWVAutofillController*)autofillController saveCreditCardWithSaver:(CWVCreditCardSaver*)saver; +// Called if the card holder's name needs to be confirmed by the user before the +// card can be saved. This can happen if a user doesn't have a GPay account or +// attempted to save a credit card without providing a name for it. +// |fixer| encapsulates information needed to assist with this fix attempt. +// Life time of |fixer| should be managed by the delegate. +- (void)autofillController:(CWVAutofillController*)autofillController + confirmCreditCardNameWithFixer:(CWVCreditCardNameFixer*)fixer; + +// Called if the card's expiration needs to be corrected before the the card can +// be saved. This can happen if a user attempted to save a credit card with an +// expired expiration date. +// |fixer| encapsulates information needed to assist with this fix attempt. +// Life time of |fixer| should be managed by the delegate. +- (void)autofillController:(CWVAutofillController*)autofillController + confirmCreditCardExpirationWithFixer:(CWVCreditCardExpirationFixer*)fixer; + // Called when the user needs to use |verifier| to verify a credit card. // Lifetime of |verifier| should be managed by the delegate. - (void)autofillController:(CWVAutofillController*)autofillController
diff --git a/ios/web_view/tools/build.py b/ios/web_view/tools/build.py index c876d0e..819d554 100755 --- a/ios/web_view/tools/build.py +++ b/ios/web_view/tools/build.py
@@ -186,10 +186,6 @@ help='Additional gn args to pass through to ninja.') parser.add_argument('--include_cronet', action='store_true', help='Combines Cronet and ChromeWebView as 1 framework.') - parser.add_argument('--enable_sync', action='store_true', - help='Enables public API for sync.') - parser.add_argument('--enable_autofill', action='store_true', - help='Enables public API for autofill.') build_configs = ['Debug', 'Release'] target_devices = ['iphonesimulator', 'iphoneos'] parser.add_argument('--build_configs', nargs='+', default=build_configs, @@ -221,14 +217,6 @@ output_name = 'CronetChromeWebView' else: extra_gn_options += 'ios_web_view_include_cronet=false ' - if options.enable_sync: - extra_gn_options += 'ios_web_view_enable_sync=true ' - else: - extra_gn_options += 'ios_web_view_enable_sync=false ' - if options.enable_autofill: - extra_gn_options += 'ios_web_view_enable_autofill=true ' - else: - extra_gn_options += 'ios_web_view_enable_autofill=false ' extra_gn_options += 'ios_web_view_output_name="%s" ' % output_name # This prevents Breakpad from being included in the final binary to avoid # duplicate symbols with the client app.
diff --git a/media/capture/content/video_capture_oracle.cc b/media/capture/content/video_capture_oracle.cc index 5e8d29df..2a1e3c1 100644 --- a/media/capture/content/video_capture_oracle.cc +++ b/media/capture/content/video_capture_oracle.cc
@@ -6,6 +6,7 @@ #include <algorithm> +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/numerics/safe_conversions.h" @@ -412,6 +413,15 @@ const int decreased_area = AnalyzeForDecreasedArea(analyze_time); if (decreased_area > 0) { resolution_chooser_.SetTargetFrameArea(decreased_area); + if (!emit_log_message_cb_.is_null()) { + emit_log_message_cb_.Run(base::StringPrintf( + "VFC: CaptureOracle - Decreasing resolution. " + "buffer_utilization_: %lf " + "estimated_cappable_area: %lf " + "capture_size: %s ", + buffer_pool_utilization_.current(), estimated_capable_area_.current(), + capture_size_.ToString().c_str())); + } return; } @@ -587,4 +597,9 @@ (now - accumulator.update_time() <= kMaxTimeSinceLastFeedbackUpdate); } +void VideoCaptureOracle::SetLogCallback( + base::RepeatingCallback<void(const std::string&)> emit_log_cb) { + emit_log_message_cb_ = std::move(emit_log_cb); +} + } // namespace media
diff --git a/media/capture/content/video_capture_oracle.h b/media/capture/content/video_capture_oracle.h index c1eb299..212b8be4 100644 --- a/media/capture/content/video_capture_oracle.h +++ b/media/capture/content/video_capture_oracle.h
@@ -5,7 +5,7 @@ #ifndef MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_ #define MEDIA_CAPTURE_CONTENT_VIDEO_CAPTURE_ORACLE_H_ -#include "base/callback_forward.h" +#include "base/callback.h" #include "base/time/time.h" #include "media/base/feedback_signal_accumulator.h" #include "media/capture/capture_export.h" @@ -139,6 +139,11 @@ static constexpr base::TimeDelta kDefaultMinSizeChangePeriod = base::TimeDelta::FromSeconds(3); + void SetLogCallback( + base::RepeatingCallback<void(const std::string&)> emit_log_cb); + + void Log(const std::string& message); + private: // Retrieve/Assign a frame timestamp by capture |frame_number|. Only valid // when IsFrameInRecentHistory(frame_number) returns true. @@ -253,6 +258,10 @@ // animation. This determines whether capture size increases will be // aggressive (because content is not animating). base::TimeTicks last_time_animation_was_detected_; + + // Callback for webrtc native log. It should check for corresponding feature + // inside. + base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_; }; } // namespace media
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index ee5c443..31ca817 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -47,6 +47,10 @@ // Maximum number of requests that can be created. constexpr size_t kMaxNumRequests = 32; +gfx::Rect V4L2RectToGfxRect(const v4l2_rect& rect) { + return gfx::Rect(rect.left, rect.top, rect.width, rect.height); +} + } // namespace V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id) { @@ -881,6 +885,57 @@ return current_format_; } +std::pair<base::Optional<struct v4l2_format>, int> V4L2Queue::GetFormat() { + struct v4l2_format format = {}; + format.type = type_; + if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { + VPQLOGF(2) << "Failed to get format"; + return std::make_pair(base::nullopt, errno); + } + + return std::make_pair(format, 0); +} + +base::Optional<gfx::Rect> V4L2Queue::GetVisibleRect() { + // Some drivers prior to 4.13 only accept the non-MPLANE variant when using + // VIDIOC_G_SELECTION. This block can be removed once we stop supporting + // kernels < 4.13. + // For details, see the note at + // https://www.kernel.org/doc/html/latest/media/uapi/v4l/vidioc-g-selection.html + enum v4l2_buf_type compose_type; + switch (type_) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + compose_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + break; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + compose_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + break; + default: + compose_type = type_; + break; + } + + struct v4l2_selection selection = {}; + selection.type = compose_type; + selection.target = V4L2_SEL_TGT_COMPOSE; + if (device_->Ioctl(VIDIOC_G_SELECTION, &selection) == 0) { + DVQLOGF(3) << "VIDIOC_G_SELECTION is supported"; + return V4L2RectToGfxRect(selection.r); + } + + // TODO(acourbot) using VIDIOC_G_CROP is considered legacy and can be + // removed once no active devices use it anymore. + DVQLOGF(3) << "Fallback to VIDIOC_G_CROP"; + struct v4l2_crop crop = {}; + crop.type = type_; + if (device_->Ioctl(VIDIOC_G_CROP, &crop) == 0) { + return V4L2RectToGfxRect(crop.c); + } + + VQLOGF(1) << "Failed to get visible rect"; + return base::nullopt; +} + size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!free_buffers_); @@ -906,13 +961,12 @@ // This should not be required, but Tegra's VIDIOC_QUERYBUF will fail on // output buffers if the number of specified planes does not exactly match the // format. - struct v4l2_format format = {.type = type_}; - int ret = device_->Ioctl(VIDIOC_G_FMT, &format); - if (ret) { - VPQLOGF(1) << "VIDIOC_G_FMT failed"; + base::Optional<v4l2_format> format = GetFormat().first; + if (!format) { + VQLOGF(1) << "Cannot get format."; return 0; } - planes_count_ = format.fmt.pix_mp.num_planes; + planes_count_ = format->fmt.pix_mp.num_planes; DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES)); struct v4l2_requestbuffers reqbufs = {}; @@ -921,7 +975,7 @@ reqbufs.memory = memory; DVQLOGF(3) << "Requesting " << count << " buffers."; - ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); + int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs); if (ret) { VPQLOGF(1) << "VIDIOC_REQBUFS failed"; return 0; @@ -934,7 +988,7 @@ // Now query all buffer information. for (size_t i = 0; i < reqbufs.count; i++) { - auto buffer = V4L2Buffer::Create(device_, type_, memory_, format, i); + auto buffer = V4L2Buffer::Create(device_, type_, memory_, *format, i); if (!buffer) { DeallocateBuffers();
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h index 346ec0c9..a8e76ce 100644 --- a/media/gpu/v4l2/v4l2_device.h +++ b/media/gpu/v4l2/v4l2_device.h
@@ -293,6 +293,26 @@ size_t buffer_size) WARN_UNUSED_RESULT; + // Returns the currently set format on the queue. The result is returned as + // a std::pair where the first member is the format, or base::nullopt if the + // format could not be obtained due to an ioctl error. The second member is + // only used in case of an error and contains the |errno| set by the failing + // ioctl. If the first member is not base::nullopt, the second member will + // always be zero. + // + // If the second member is 0, then the first member is guaranteed to have + // a valid value. So clients that are not interested in the precise error + // message can just check that the first member is valid and go on. + // + // This pair is used because not all failures to get the format are + // necessarily errors, so we need to way to let the use decide whether it + // is one or not. + std::pair<base::Optional<struct v4l2_format>, int> GetFormat(); + + // Codec-specific method to get the visible rectangle of the queue, using the + // VIDIOC_G_SELECTION ioctl if available, or VIDIOC_G_CROP as a fallback. + base::Optional<gfx::Rect> GetVisibleRect(); + // Allocate |count| buffers for the current format of this queue, with a // specific |memory| allocation, and returns the number of buffers allocated // or zero if an error occurred, or if references to any previously allocated
diff --git a/media/gpu/v4l2/v4l2_image_processor_backend.cc b/media/gpu/v4l2/v4l2_image_processor_backend.cc index 12eeef48..6498537 100644 --- a/media/gpu/v4l2/v4l2_image_processor_backend.cc +++ b/media/gpu/v4l2/v4l2_image_processor_backend.cc
@@ -574,6 +574,33 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_); while (!input_job_queue_.empty()) { + if (!input_queue_->IsStreaming()) { + const VideoFrame& input_frame = + *(input_job_queue_.front()->input_frame.get()); + const gfx::Size input_buffer_size(input_frame.stride(0), + input_frame.coded_size().height()); + if (!ReconfigureV4L2Format(input_buffer_size, input_frame.visible_rect(), + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) { + NotifyError(); + return; + } + } + + if (input_job_queue_.front() + ->output_frame && // output_frame is nullptr in ALLOCATE mode. + !output_queue_->IsStreaming()) { + const VideoFrame& output_frame = + *(input_job_queue_.front()->output_frame.get()); + const gfx::Size output_buffer_size(output_frame.stride(0), + output_frame.coded_size().height()); + if (!ReconfigureV4L2Format(output_buffer_size, + output_frame.visible_rect(), + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) { + NotifyError(); + return; + } + } + // We need one input and one output buffer to schedule the job auto input_buffer = input_queue_->GetFreeBuffer(); auto output_buffer = output_queue_->GetFreeBuffer(); @@ -641,6 +668,39 @@ return true; } +bool V4L2ImageProcessorBackend::ReconfigureV4L2Format( + const gfx::Size& size, + const gfx::Rect& visible_rect, + enum v4l2_buf_type type) { + v4l2_format format{}; + format.type = type; + if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { + VPLOGF(1) << "ioctl() failed: VIDIOC_G_FMT"; + return false; + } + + if (static_cast<int>(format.fmt.pix_mp.width) == size.width() && + static_cast<int>(format.fmt.pix_mp.height) == size.height()) { + return true; + } + format.fmt.pix_mp.width = size.width(); + format.fmt.pix_mp.height = size.height(); + if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) { + VPLOGF(1) << "ioctl() failed: VIDIOC_S_FMT"; + return false; + } + if (!ApplyCrop(visible_rect, type)) { + return false; + } + + auto queue = device_->GetQueue(type); + const size_t num_buffers = queue->AllocatedBuffersCount(); + const v4l2_memory memory_type = queue->GetMemoryType(); + DCHECK_GT(num_buffers, 0u); + return queue->DeallocateBuffers() && + AllocateV4L2Buffers(queue.get(), num_buffers, memory_type); +} + bool V4L2ImageProcessorBackend::CreateInputBuffers() { VLOGF(2); DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);
diff --git a/media/gpu/v4l2/v4l2_image_processor_backend.h b/media/gpu/v4l2/v4l2_image_processor_backend.h index 5214eeb..bd1c78ac 100644 --- a/media/gpu/v4l2/v4l2_image_processor_backend.h +++ b/media/gpu/v4l2/v4l2_image_processor_backend.h
@@ -135,6 +135,10 @@ bool CreateOutputBuffers(); // Specify |visible_rect| to v4l2 |type| queue. bool ApplyCrop(const gfx::Rect& visible_rect, enum v4l2_buf_type type); + // Reconfigure |size| and |visible_rect| to v4l2 |type| queue. + bool ReconfigureV4L2Format(const gfx::Size& size, + const gfx::Rect& visible_rect, + enum v4l2_buf_type type); // Callback of VideoFrame destruction. Since VideoFrame destruction // callback might be executed on any sequence, we use a thunk to post the
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc index 4f9ff1d5..dd2c2e8 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -649,15 +649,12 @@ // Since VdaVideoDecoder doesn't allocate PictureBuffer with size adjusted by // itself, we have to adjust here. - struct v4l2_format format; - memset(&format, 0, sizeof(format)); - format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - - if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { - PLOG(ERROR) << "Failed getting OUTPUT format"; + auto ret = input_queue_->GetFormat().first; + if (!ret) { NOTIFY_ERROR(PLATFORM_FAILURE); return false; } + struct v4l2_format format = std::move(*ret); format.fmt.pix_mp.width = pic_size.width(); format.fmt.pix_mp.height = pic_size.height(); @@ -669,13 +666,12 @@ } // Get the coded size from the CAPTURE queue - memset(&format, 0, sizeof(format)); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { - PLOG(ERROR) << "Failed getting CAPTURE format"; + ret = output_queue_->GetFormat().first; + if (!ret) { NOTIFY_ERROR(PLATFORM_FAILURE); return false; } + format = std::move(*ret); coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width), base::checked_cast<int>(format.fmt.pix_mp.height));
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc index 7147d9f..928bec4 100644 --- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -2084,18 +2084,19 @@ DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); *again = false; - memset(format, 0, sizeof(*format)); - format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - if (device_->Ioctl(VIDIOC_G_FMT, format) != 0) { - if (errno == EINVAL) { + + auto ret = output_queue_->GetFormat(); + switch (ret.second) { + case 0: + *format = *ret.first; + break; + case EINVAL: // EINVAL means we haven't seen sufficient stream to decode the format. *again = true; return true; - } else { - PLOG(ERROR) << "ioctl() failed: VIDIOC_G_FMT"; + default: NOTIFY_ERROR(PLATFORM_FAILURE); return false; - } } // Make sure we are still getting the format we set on initialization. @@ -2146,30 +2147,11 @@ const gfx::Size& coded_size) { DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); - struct v4l2_rect* visible_rect; - struct v4l2_selection selection_arg; - memset(&selection_arg, 0, sizeof(selection_arg)); - selection_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - selection_arg.target = V4L2_SEL_TGT_COMPOSE; - - if (device_->Ioctl(VIDIOC_G_SELECTION, &selection_arg) == 0) { - DVLOGF(3) << "VIDIOC_G_SELECTION is supported"; - visible_rect = &selection_arg.r; - } else { - DVLOGF(3) << "Fallback to VIDIOC_G_CROP"; - struct v4l2_crop crop_arg; - memset(&crop_arg, 0, sizeof(crop_arg)); - crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - - if (device_->Ioctl(VIDIOC_G_CROP, &crop_arg) != 0) { - VPLOGF(1) << "ioctl() VIDIOC_G_CROP failed"; - return coded_size; - } - visible_rect = &crop_arg.c; + auto ret = output_queue_->GetVisibleRect(); + if (!ret) { + return coded_size; } - - gfx::Rect rect(visible_rect->left, visible_rect->top, visible_rect->width, - visible_rect->height); + gfx::Rect rect = std::move(*ret); DVLOGF(3) << "visible rectangle is " << rect.ToString(); if (!gfx::Rect(coded_size).Contains(rect)) { DVLOGF(3) << "visible rectangle " << rect.ToString()
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateless.cc b/media/gpu/v4l2/v4l2_video_decoder_backend_stateless.cc index 3ca859a4..b8c3400 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateless.cc +++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateless.cc
@@ -529,13 +529,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u); - struct v4l2_format format = {}; - - format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - if (device_->Ioctl(VIDIOC_G_FMT, &format) != 0) { + auto ret = input_queue_->GetFormat().first; + if (!ret) { VPLOGF(1) << "Failed getting OUTPUT format"; return false; } + struct v4l2_format format = std::move(*ret); format.fmt.pix_mp.width = pic_size.width(); format.fmt.pix_mp.height = pic_size.height();
diff --git a/printing/BUILD.gn b/printing/BUILD.gn index 9b19b2d..246c15c7 100644 --- a/printing/BUILD.gn +++ b/printing/BUILD.gn
@@ -31,13 +31,19 @@ "set enable_pdf=true.") } +# Enable the CUPS IPP printing backend. +# TODO(crbug.com/226176): Remove this after CUPS PPD API calls are removed. +declare_args() { + use_cups_ipp = use_cups && !is_desktop_linux +} + # Several targets want to include this header file. We separate it out # here so multiple targets can depend on it. source_set("printing_export") { sources = [ "printing_export.h" ] } -if (use_cups && is_chromeos) { +if (use_cups_ipp && is_chromeos) { ipp_handler_map_path = "$target_gen_dir/backend/ipp_handler_map.cc" ipp_code_generate("ipp_handlers_generate") { @@ -217,7 +223,7 @@ # of the print backend and enables a custom implementation instead. defines += [ "PRINT_BACKEND_AVAILABLE" ] - if (is_chromeos || is_mac) { + if (use_cups_ipp) { sources += [ "backend/cups_connection.cc", "backend/cups_connection.h", @@ -271,7 +277,7 @@ } } - if (is_chromeos || is_mac) { + if (use_cups_ipp || is_chromeos) { sources += [ "printer_query_result.h", "printer_status.cc", @@ -370,7 +376,7 @@ if (use_cups) { configs += [ ":cups" ] - if (is_chromeos || is_mac) { + if (use_cups_ipp) { sources += [ "backend/cups_ipp_helper_unittest.cc" ] }
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom index c1ae4fe..331efbe 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -52,6 +52,9 @@ // Indicates that OnFrameCaptured() will not be called again, an end-of-stream // signal. OnStopped(); + // Called to deliver a log message to the consumer. + // Currently used to populate WebRTC native logs. + OnLog(string message); }; // Interface to an implementation that captures the frames of a
diff --git a/services/viz/public/cpp/compositing/quads_mojom_traits.h b/services/viz/public/cpp/compositing/quads_mojom_traits.h index ea4d147..8054def 100644 --- a/services/viz/public/cpp/compositing/quads_mojom_traits.h +++ b/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -544,11 +544,13 @@ template <> struct StructTraits<viz::mojom::DrawQuadDataView, DrawQuadWithSharedQuadState> { static const gfx::Rect& rect(const DrawQuadWithSharedQuadState& input) { + DCHECK(input.quad->rect.size().GetCheckedArea().IsValid()); return input.quad->rect; } static const gfx::Rect& visible_rect( const DrawQuadWithSharedQuadState& input) { + DCHECK(input.quad->rect.Contains(input.quad->visible_rect)); return input.quad->visible_rect; }
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index 7077c9d..72531bd 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -171,6 +171,7 @@ 'tools_unittests', 'video_engine_tests', 'voice_engine_unittests', + 'voip_unittests', 'webrtc_nonparallel_tests', 'xmllite_xmpp_unittests',
diff --git a/testing/test.gni b/testing/test.gni index eda4330..d2b54c2 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -217,7 +217,7 @@ package = ":$_pkg_target" package_name_override = _output_name - deps = [ "//testing/buildbot/filters:fuchsia_filters" ] + data_deps = [ "//testing/buildbot/filters:fuchsia_filters" ] } cr_fuchsia_package(_pkg_target) {
diff --git a/third_party/binutils/README.chromium b/third_party/binutils/README.chromium index b40ec3c..3dc5547 100644 --- a/third_party/binutils/README.chromium +++ b/third_party/binutils/README.chromium
@@ -1,6 +1,7 @@ Name: binutils URL: http://www.gnu.org/software/binutils/ Version: 2.30 +CPEPrefix: cpe:/a:gnu:binutils:2.30 License: GPL v2 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/blink/public/mojom/use_counter/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/css_property_id.mojom index dfc2bf2..07465f3 100644 --- a/third_party/blink/public/mojom/use_counter/css_property_id.mojom +++ b/third_party/blink/public/mojom/use_counter/css_property_id.mojom
@@ -218,7 +218,7 @@ kAliasWebkitAnimationName = 172, kAliasWebkitAnimationPlayState = 173, kAliasWebkitAnimationTimingFunction = 174, - kWebkitAppearance = 175, + kAliasWebkitAppearance = 175, // kWebkitAspectRatio = 176, kAliasWebkitBackfaceVisibility = 177, kAliasWebkitBackgroundClip = 178, @@ -701,6 +701,7 @@ kSubtreeVisibility = 655, kMathStyle = 656, kAspectRatio = 657, + kAppearance = 658, // 1. Add new features above this line (don't change the assigned numbers of // the existing items). // 2. Run the src/tools/metrics/histograms/update_use_counter_css.py script
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 19c5293..a416dc5 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2225,7 +2225,7 @@ kV8RTCRtpReceiver_JitterBufferDelayHint_AttributeGetter = 2886, kV8RTCRtpReceiver_JitterBufferDelayHint_AttributeSetter = 2887, kMediaCapabilitiesDecodingInfoWithKeySystemConfig = 2888, - kRevertInCustomIdent = 2889, + kOBSOLETE_RevertInCustomIdent = 2889, kUnoptimizedImagePolicies = 2890, kVTTCueParser = 2891, kMediaElementTextTrackContainer = 2892, @@ -2536,6 +2536,9 @@ kCrossOriginOpenerPolicySameOriginAllowPopups = 3198, kCrossOriginEmbedderPolicyRequireCorp = 3199, kCoopAndCoepIsolated = 3200, + // The above items are available in M83 branch. + + kWrongBaselineOfButtonElement = 3201, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc index 59b2a13b..7dafcca 100644 --- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc +++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
@@ -232,6 +232,40 @@ : nullptr; } +v8::MaybeLocal<v8::Function> CreateNamedConstructorFunction( + ScriptState* script_state, + v8::FunctionCallback callback, + const char* func_name, + int func_length, + const WrapperTypeInfo* wrapper_type_info) { + v8::Isolate* isolate = script_state->GetIsolate(); + const DOMWrapperWorld& world = script_state->World(); + V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(isolate); + const void* callback_key = reinterpret_cast<const void*>(callback); + + // Named constructors are not interface objcets (despite that they're + // pretending so), but we reuse the cache of interface objects, which just + // works because both are V8 function template. + v8::Local<v8::FunctionTemplate> function_template = + per_isolate_data->FindInterfaceTemplate(world, callback_key); + if (function_template.IsEmpty()) { + function_template = v8::FunctionTemplate::New( + isolate, callback, v8::Local<v8::Value>(), v8::Local<v8::Signature>(), + func_length, v8::ConstructorBehavior::kAllow, + v8::SideEffectType::kHasSideEffect); + v8::Local<v8::FunctionTemplate> interface_template = + wrapper_type_info->DomTemplate(isolate, world); + function_template->SetPrototypeProviderTemplate(interface_template); + function_template->ReadOnlyPrototype(); + function_template->SetClassName(V8AtomicString(isolate, func_name)); + function_template->InstanceTemplate()->SetInternalFieldCount( + kV8DefaultWrapperInternalFieldCount); + per_isolate_data->SetInterfaceTemplate(world, callback_key, + function_template); + } + return function_template->GetFunction(script_state->GetContext()); +} + v8::Local<v8::Array> EnumerateIndexedProperties(v8::Isolate* isolate, uint32_t length) { Vector<v8::Local<v8::Value>> elements;
diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h index b461f47..4907fc9 100644 --- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h +++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
@@ -151,6 +151,13 @@ CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( const DOMParser* parser); +CORE_EXPORT v8::MaybeLocal<v8::Function> CreateNamedConstructorFunction( + ScriptState* script_state, + v8::FunctionCallback callback, + const char* func_name, + int func_length, + const WrapperTypeInfo* wrapper_type_info); + CORE_EXPORT v8::Local<v8::Array> EnumerateIndexedProperties( v8::Isolate* isolate, uint32_t length);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc b/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc index 6809daa..53926f2 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.cc
@@ -725,13 +725,13 @@ static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete), v8::Local<v8::AccessorSignature>(), v8::DEFAULT, v8::SideEffectType::kHasNoSideEffect, - v8::SideEffectType::kHasNoSideEffect); + v8::SideEffectType::kHasSideEffect); prototype_template->SetNativeDataProperty( name, constants[i].getter, nullptr, v8::Local<v8::Value>(), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete), v8::Local<v8::AccessorSignature>(), v8::DEFAULT, v8::SideEffectType::kHasNoSideEffect, - v8::SideEffectType::kHasNoSideEffect); + v8::SideEffectType::kHasSideEffect); } }
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index 0650640..2e98dff 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -63,12 +63,16 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_native_scroll_behavior.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_navigation_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_navigation_type.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_operation_type.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_operation_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_playback_direction.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_playback_direction.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_premultiply_alpha.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_premultiply_alpha.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_referrer_policy.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_referrer_policy.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_refresh_policy.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_refresh_policy.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_replace_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_replace_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_request_cache.cc", @@ -107,6 +111,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_selection_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_shadow_root_mode.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_shadow_root_mode.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_sign_request_data.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_sign_request_data.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_slot_assignment_mode.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_slot_assignment_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_supported_type.cc",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index fac8c3d..997d5288 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -91,6 +91,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_cull_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_error_filter.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_error_filter.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_extension_name.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_extension_name.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_filter_mode.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_filter_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_front_face.cc", @@ -185,6 +187,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_orientation_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_oscillator_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_oscillator_type.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_otp_credential_transport_type.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_otp_credential_transport_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_over_sample_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_over_sample_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_panning_model_type.cc", @@ -219,6 +223,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_bundle_policy.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_data_channel_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_data_channel_state.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_degradation_preference.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_degradation_preference.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_transport_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_dtls_transport_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_error_detail_type.cc",
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py index ae9defa4..7ef1ef1 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
@@ -71,6 +71,7 @@ "constructor_group": None, "dict_member": None, "exposed_construct": None, + "is_named_constructor": False, "legacy_window_alias": None, "operation": None, "operation_group": None,
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index 9d2ce69..e00dbd2e 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -126,10 +126,15 @@ elif cg_context.constant: kind = "Constant" elif cg_context.constructor_group: - property_name = "" - kind = "Constructor" + if cg_context.is_named_constructor: + kind = "NamedConstructor" + else: + property_name = "" + kind = "Constructor" elif cg_context.exposed_construct: - if cg_context.legacy_window_alias: + if cg_context.is_named_constructor: + kind = "NamedConstructorProperty" + elif cg_context.legacy_window_alias: kind = "LegacyWindowAlias" else: kind = "ExposedConstruct" @@ -562,7 +567,10 @@ func_name = backward_compatible_api_func(cg_context) if cg_context.constructor: - func_name = "Create" + if cg_context.is_named_constructor: + func_name = "CreateForJSConstructor" + else: + func_name = "Create" if "Reflect" in ext_attrs: # [Reflect] func_name = _make_reflect_accessor_func_name(cg_context) @@ -676,7 +684,7 @@ event_name = "{}.{}".format(event_name, "get") elif cg_context.attribute_set: event_name = "{}.{}".format(event_name, "set") - elif cg_context.constructor_group: + elif cg_context.constructor_group and not cg_context.is_named_constructor: event_name = "{}.{}".format(cg_context.class_like.identifier, "constructor") @@ -729,7 +737,7 @@ T = TextNode - return SequenceNode([ + node = SequenceNode([ CxxUnlikelyIfNode( cond="!${info}.IsConstructCall()", body=T("${exception_state}.ThrowTypeError(" @@ -742,6 +750,11 @@ body=T("bindings::V8SetReturnValue(${info}, ${v8_receiver});\n" "return;")), ]) + node.accumulate( + CodeGenAccumulator.require_include_headers([ + "third_party/blink/renderer/platform/bindings/v8_object_constructor.h", + ])) + return node def make_check_receiver(cg_context): @@ -1732,6 +1745,80 @@ return func_def +def make_named_constructor_property_callback_def(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = _make_empty_callback_def(cg_context, function_name) + body = func_def.body + + body.extend([ + make_runtime_call_timer_scope(cg_context), + make_bindings_trace_event(cg_context), + make_report_deprecate_as(cg_context), + make_report_measure_as(cg_context), + make_log_activity(cg_context), + EmptyNode(), + ]) + + constructor_group = cg_context.exposed_construct + assert isinstance(constructor_group, web_idl.ConstructorGroup) + assert isinstance(constructor_group.owner, web_idl.Interface) + named_ctor_v8_bridge = v8_bridge_class_name(constructor_group.owner) + cgc = CodeGenContext( + interface=constructor_group.owner, + constructor_group=constructor_group, + is_named_constructor=True, + class_name=named_ctor_v8_bridge) + named_ctor_name = callback_function_name(cgc) + named_ctor_def = make_constructor_callback_def(cgc, named_ctor_name) + + return_value_cache_return_early = """\ +static const V8PrivateProperty::SymbolKey kPrivatePropertyNamedConstructor; +auto&& v8_private_named_constructor = + V8PrivateProperty::GetSymbol(${isolate}, kPrivatePropertyNamedConstructor); +v8::Local<v8::Value> v8_named_constructor; +if (v8_private_named_constructor.GetOrUndefined(${v8_receiver}) + .ToLocal(&v8_named_constructor) && + !v8_named_constructor->IsUndefined()) { + bindings::V8SetReturnValue(${info}, v8_named_constructor); + return; +} +""" + + pattern = """\ +v8::Local<v8::Function> v8_function; +if (!bindings::CreateNamedConstructorFunction( + ${script_state}, + {callback}, + "{func_name}", + {func_length}, + {v8_bridge}::GetWrapperTypeInfo()) + .ToLocal(&v8_function)) { + return; +} +bindings::V8SetReturnValue(${info}, v8_function); +""" + create_named_constructor_function = _format( + pattern, + callback=named_ctor_name, + func_name=constructor_group.identifier, + func_length=constructor_group.min_num_of_required_arguments, + v8_bridge=named_ctor_v8_bridge) + + return_value_cache_update_value = """\ +v8_private_named_constructor.Set(${v8_receiver}, v8_function); +""" + + body.extend([ + TextNode(return_value_cache_return_early), + TextNode(create_named_constructor_function), + TextNode(return_value_cache_update_value), + ]) + + return SequenceNode([named_ctor_def, EmptyNode(), func_def]) + + def make_operation_entry(cg_context): assert isinstance(cg_context, CodeGenContext) @@ -3271,6 +3358,31 @@ exposed_construct=exposed_construct, prop_callback_name=prop_callback_name)) + def process_named_constructor_group(named_constructor_group, + is_context_dependent, + exposure_conditional, world): + cgc = cg_context.make_copy( + exposed_construct=named_constructor_group, + is_named_constructor=True, + for_world=world, + v8_callback_type=CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK) + prop_callback_name = callback_function_name(cgc) + prop_callback_node = make_named_constructor_property_callback_def( + cgc, prop_callback_name) + + callback_def_nodes.extend([ + prop_callback_node, + EmptyNode(), + ]) + + exposed_construct_entries.append( + _PropEntryExposedConstruct( + is_context_dependent=is_context_dependent, + exposure_conditional=exposure_conditional, + world=world, + exposed_construct=named_constructor_group, + prop_callback_name=prop_callback_name)) + def process_operation_group(operation_group, is_context_dependent, exposure_conditional, world): cgc = cg_context.make_copy( @@ -3318,6 +3430,12 @@ iterate(interface.constructor_groups, process_constructor_group) iterate(interface.exposed_constructs, process_exposed_construct) iterate(interface.legacy_window_aliases, process_exposed_construct) + named_constructor_groups = [ + group for construct in interface.exposed_constructs + for group in construct.named_constructor_groups + if construct.named_constructor_groups + ] + iterate(named_constructor_groups, process_named_constructor_group) iterate(interface.operation_groups, process_operation_group) if interface.stringifier: iterate([interface.stringifier.operation], process_stringifier) @@ -4680,10 +4798,6 @@ ]) impl_source_node.accumulator.add_include_headers( _collect_include_headers(interface)) - if interface.constructor_groups: - impl_source_node.accumulator.add_include_headers([ - "third_party/blink/renderer/platform/bindings/v8_object_constructor.h", - ]) # Assemble the parts. api_header_blink_ns.body.append(api_class_def)
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl index f5a02e8..87caef2 100644 --- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/css/css_property_id_templates.h" #include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" +#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h" namespace blink { @@ -20,11 +21,8 @@ return false; } - if (valueID == CSSValueID::kInherit || valueID == CSSValueID::kInitial || - valueID == CSSValueID::kUnset) { - // These are css-wide keywords that are valid for all properties. + if (css_parsing_utils::IsCSSWideKeyword(valueID)) return true; - } switch (id) { {% for property in properties if property.keywordIDs and 'Keyword' in property.typedom_types %}
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index e9ef6e2..c83e781 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1047,6 +1047,7 @@ sources = [ "clipboard/clipboard_utilities_test.cc", "content_capture/content_capture_test.cc", + "css/css_revert_value_test.cc", "css/css_test_helpers.cc", "css/css_test_helpers.h", "css/css_uri_value_test.cc",
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_interpolation_type.cc index fcc56d7..efc95c5 100644 --- a/third_party/blink/renderer/core/animation/css_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_interpolation_type.cc
@@ -12,6 +12,8 @@ #include "third_party/blink/renderer/core/animation/string_keyframe.h" #include "third_party/blink/renderer/core/css/computed_style_css_value_mapping.h" #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" +#include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" #include "third_party/blink/renderer/core/css/parser/css_tokenizer.h" @@ -183,6 +185,11 @@ value = resolved_value; } + if (value->IsRevertValue()) { + // TODO(andruud): Actually revert instead of treating as unset. + value = cssvalue::CSSUnsetValue::Create(); + } + bool is_inherited = CssProperty().IsInherited(); if (value->IsInitialValue() || (value->IsUnsetValue() && !is_inherited)) { return MaybeConvertInitial(state, conversion_checkers);
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn index 183fd3f..3851292 100644 --- a/third_party/blink/renderer/core/css/BUILD.gn +++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -155,6 +155,8 @@ "css_reflection_direction.h", "css_resolution_units.h", "css_resource_fetch_restriction.h", + "css_revert_value.cc", + "css_revert_value.h", "css_rule.cc", "css_rule.h", "css_rule_list.h", @@ -626,6 +628,7 @@ "cssom/inline_style_property_map_test.cc", "cssom/paint_worklet_style_property_map_test.cc", "cssom/prepopulated_computed_style_property_map_test.cc", + "cssom/style_property_map_test.cc", "drag_update_test.cc", "font_face_cache_test.cc", "invalidation/invalidation_set_test.cc", @@ -643,6 +646,7 @@ "parser/css_parser_local_context_test.cc", "parser/css_parser_token_stream_test.cc", "parser/css_parser_token_test.cc", + "parser/css_property_parser_helpers_test.cc", "parser/css_property_parser_test.cc", "parser/css_selector_parser_test.cc", "parser/css_supports_parser_test.cc",
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc index 4df6327..f2b1f0d 100644 --- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc +++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -132,7 +132,7 @@ CSSPropertyID::kWillChange, CSSPropertyID::kWordBreak, CSSPropertyID::kWordSpacing, CSSPropertyID::kZIndex, CSSPropertyID::kZoom, - CSSPropertyID::kWebkitAppearance, CSSPropertyID::kBackfaceVisibility, + CSSPropertyID::kAppearance, CSSPropertyID::kBackfaceVisibility, CSSPropertyID::kWebkitBorderHorizontalSpacing, CSSPropertyID::kWebkitBorderImage, CSSPropertyID::kWebkitBorderVerticalSpacing, CSSPropertyID::kWebkitBoxAlign, @@ -433,8 +433,7 @@ String CSSComputedStyleDeclaration::GetPropertyValue( CSSPropertyID property_id) const { // allow_visited_style_ is true only for access from DevTools. - if (!allow_visited_style_ && - property_id == CSSPropertyID::kWebkitAppearance) { + if (!allow_visited_style_ && property_id == CSSPropertyID::kAppearance) { UseCounter::Count( node_->GetDocument(), WebFeature::kGetComputedStyleForWebkitAppearanceExcludeDevTools); @@ -559,7 +558,7 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal( CSSPropertyID property_id) { - if (property_id == CSSPropertyID::kWebkitAppearance && node_) { + if (property_id == CSSPropertyID::kAppearance && node_) { UseCounter::Count(node_->GetDocument(), WebFeature::kGetComputedStyleWebkitAppearance); }
diff --git a/third_party/blink/renderer/core/css/css_custom_property_declaration.h b/third_party/blink/renderer/core/css/css_custom_property_declaration.h index f7d09e70..b870b5b 100644 --- a/third_party/blink/renderer/core/css/css_custom_property_declaration.h +++ b/third_party/blink/renderer/core/css/css_custom_property_declaration.h
@@ -8,6 +8,7 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/css/css_value.h" #include "third_party/blink/renderer/core/css/css_variable_data.h" +#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -21,8 +22,7 @@ name_(name), value_(nullptr), value_id_(id) { - DCHECK(id == CSSValueID::kInherit || id == CSSValueID::kInitial || - id == CSSValueID::kUnset); + DCHECK(css_parsing_utils::IsCSSWideKeyword(id)); } CSSCustomPropertyDeclaration(const AtomicString& name,
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc index b274e03..b60c35e4 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.cc +++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -229,10 +229,7 @@ case kCalcAngle: case kCalcFrequency: case kCalcPercentLength: - case kCalcPercentNumber: case kCalcTime: - case kCalcLengthNumber: - case kCalcPercentLengthNumber: case kCalcOther: NOTREACHED(); break; @@ -285,43 +282,26 @@ // ------ End of CSSMathExpressionNumericLiteral member functions static const CalculationCategory kAddSubtractResult[kCalcOther][kCalcOther] = { - /* CalcNumber */ {kCalcNumber, kCalcLengthNumber, kCalcPercentNumber, - kCalcPercentNumber, kCalcOther, kCalcOther, kCalcOther, - kCalcOther, kCalcLengthNumber, kCalcPercentLengthNumber}, + /* CalcNumber */ {kCalcNumber, kCalcOther, kCalcOther, kCalcOther, + kCalcOther, kCalcOther, kCalcOther}, /* CalcLength */ - {kCalcLengthNumber, kCalcLength, kCalcPercentLength, kCalcOther, - kCalcPercentLength, kCalcOther, kCalcOther, kCalcOther, kCalcLengthNumber, - kCalcPercentLengthNumber}, + {kCalcOther, kCalcLength, kCalcPercentLength, kCalcPercentLength, + kCalcOther, kCalcOther, kCalcOther}, /* CalcPercent */ - {kCalcPercentNumber, kCalcPercentLength, kCalcPercent, kCalcPercentNumber, - kCalcPercentLength, kCalcOther, kCalcOther, kCalcOther, - kCalcPercentLengthNumber, kCalcPercentLengthNumber}, - /* CalcPercentNumber */ - {kCalcPercentNumber, kCalcPercentLengthNumber, kCalcPercentNumber, - kCalcPercentNumber, kCalcPercentLengthNumber, kCalcOther, kCalcOther, - kCalcOther, kCalcOther, kCalcPercentLengthNumber}, + {kCalcOther, kCalcPercentLength, kCalcPercent, kCalcPercentLength, + kCalcOther, kCalcOther, kCalcOther}, /* CalcPercentLength */ - {kCalcPercentLengthNumber, kCalcPercentLength, kCalcPercentLength, - kCalcPercentLengthNumber, kCalcPercentLength, kCalcOther, kCalcOther, - kCalcOther, kCalcOther, kCalcPercentLengthNumber}, + {kCalcOther, kCalcPercentLength, kCalcPercentLength, kCalcPercentLength, + kCalcOther, kCalcOther, kCalcOther}, /* CalcAngle */ - {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcAngle, - kCalcOther, kCalcOther, kCalcOther, kCalcOther}, + {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcAngle, kCalcOther, + kCalcOther}, /* CalcTime */ - {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, - kCalcTime, kCalcOther, kCalcOther, kCalcOther}, + {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcTime, + kCalcOther}, /* CalcFrequency */ {kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, kCalcOther, - kCalcOther, kCalcFrequency, kCalcOther, kCalcOther}, - /* CalcLengthNumber */ - {kCalcLengthNumber, kCalcLengthNumber, kCalcPercentLengthNumber, - kCalcPercentLengthNumber, kCalcPercentLengthNumber, kCalcOther, kCalcOther, - kCalcOther, kCalcLengthNumber, kCalcPercentLengthNumber}, - /* CalcPercentLengthNumber */ - {kCalcPercentLengthNumber, kCalcPercentLengthNumber, - kCalcPercentLengthNumber, kCalcPercentLengthNumber, - kCalcPercentLengthNumber, kCalcOther, kCalcOther, kCalcOther, - kCalcPercentLengthNumber, kCalcPercentLengthNumber}}; + kCalcFrequency}}; static CalculationCategory DetermineCategory( const CSSMathExpressionNode& left_side, @@ -729,9 +709,6 @@ case kCalcFrequency: return CSSPrimitiveValue::UnitType::kHertz; case kCalcPercentLength: - case kCalcPercentNumber: - case kCalcLengthNumber: - case kCalcPercentLengthNumber: case kCalcOther: return CSSPrimitiveValue::UnitType::kUnknown; }
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h index b1e932b6..1d1b76f 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.h +++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -47,17 +47,14 @@ // The order of this enum should not change since its elements are used as // indices in the addSubtractResult matrix. enum CalculationCategory { - kCalcNumber = 0, + kCalcNumber, kCalcLength, kCalcPercent, - kCalcPercentNumber, kCalcPercentLength, kCalcAngle, kCalcTime, kCalcFrequency, - kCalcLengthNumber, - kCalcPercentLengthNumber, - kCalcOther + kCalcOther, }; class CORE_EXPORT CSSMathExpressionNode @@ -121,9 +118,7 @@ CalculationCategory Category() const { return category_; } bool HasPercentage() const { - return category_ == kCalcPercent || category_ == kCalcPercentNumber || - category_ == kCalcPercentLength || - category_ == kCalcPercentLengthNumber; + return category_ == kCalcPercent || category_ == kCalcPercentLength; } // Returns the unit type of the math expression *without doing any type
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 3f4c10be..5f83f4d 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2634,7 +2634,6 @@ field_template: "primitive", default_value: "0", type_name: "int", - computed_style_custom_functions: ["getter"], converter: "ConvertComputedLength<int>", typedom_types: ["Length"], valid_for_cue: true, @@ -3732,8 +3731,8 @@ converter: "ConvertLength", }, { - name: "-webkit-appearance", - property_methods: ["CSSValueFromComputedStyleInternal"], + name: "appearance", + property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"], field_group: "*", field_size: 5, field_template: "primitive", @@ -3742,6 +3741,10 @@ type_name: "ControlPart", }, { + name: "-webkit-appearance", + alias_for: "appearance", + }, + { name: "-webkit-app-region", property_methods: ["CSSValueFromComputedStyleInternal"], field_group: "*",
diff --git a/third_party/blink/renderer/core/css/css_revert_value.cc b/third_party/blink/renderer/core/css/css_revert_value.cc new file mode 100644 index 0000000..e0d1b7b --- /dev/null +++ b/third_party/blink/renderer/core/css/css_revert_value.cc
@@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/css_revert_value.h" + +#include "third_party/blink/renderer/core/css/css_value_pool.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { +namespace cssvalue { + +CSSRevertValue* CSSRevertValue::Create() { + DCHECK(RuntimeEnabledFeatures::CSSRevertEnabled()); + return CssValuePool().RevertValue(); +} + +String CSSRevertValue::CustomCSSText() const { + return "revert"; +} + +} // namespace cssvalue +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_revert_value.h b/third_party/blink/renderer/core/css/css_revert_value.h new file mode 100644 index 0000000..5630c91 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_revert_value.h
@@ -0,0 +1,44 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/util/type_safety/pass_key.h" +#include "third_party/blink/renderer/core/css/css_value.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" + +namespace blink { + +class CSSValuePool; + +namespace cssvalue { + +class CORE_EXPORT CSSRevertValue : public CSSValue { + public: + static CSSRevertValue* Create(); + + explicit CSSRevertValue(util::PassKey<CSSValuePool>) + : CSSValue(kRevertClass) {} + + String CustomCSSText() const; + + bool Equals(const CSSRevertValue&) const { return true; } + + void TraceAfterDispatch(blink::Visitor* visitor) { + CSSValue::TraceAfterDispatch(visitor); + } +}; + +} // namespace cssvalue + +template <> +struct DowncastTraits<cssvalue::CSSRevertValue> { + static bool AllowFrom(const CSSValue& value) { return value.IsRevertValue(); } +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_REVERT_VALUE_H_
diff --git a/third_party/blink/renderer/core/css/css_revert_value_test.cc b/third_party/blink/renderer/core/css/css_revert_value_test.cc new file mode 100644 index 0000000..a3508c2 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_revert_value_test.cc
@@ -0,0 +1,36 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/css_revert_value.h" +#include "third_party/blink/renderer/core/css/css_initial_value.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +using CSSRevertValue = cssvalue::CSSRevertValue; + +TEST(CSSRevertValueTest, IsCSSWideKeyword) { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_TRUE(CSSRevertValue::Create()->IsCSSWideKeyword()); +} + +TEST(CSSRevertValueTest, CssText) { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_EQ("revert", CSSRevertValue::Create()->CssText()); +} + +TEST(CSSRevertValueTest, Equals) { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_EQ(*CSSRevertValue::Create(), *CSSRevertValue::Create()); +} + +TEST(CSSRevertValueTest, NotEquals) { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_FALSE(*CSSRevertValue::Create() == *CSSInitialValue::Create()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_style_declaration_test.cc b/third_party/blink/renderer/core/css/css_style_declaration_test.cc index f4a1572..5bfe780 100644 --- a/third_party/blink/renderer/core/css/css_style_declaration_test.cc +++ b/third_party/blink/renderer/core/css/css_style_declaration_test.cc
@@ -7,6 +7,8 @@ #include "third_party/blink/renderer/core/css/css_rule_list.h" #include "third_party/blink/renderer/core/css/css_style_rule.h" #include "third_party/blink/renderer/core/css/css_test_helpers.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,4 +27,62 @@ EXPECT_EQ(AtomicString(), style->GetPropertyShorthand("padding")); } +TEST(CSSStyleDeclarationTest, ParsingRevertWithFeatureEnabled) { + ScopedCSSRevertForTest scoped_revert(true); + + css_test_helpers::TestStyleSheet sheet; + sheet.AddCSSRules("div { top: revert; --x: revert; }"); + ASSERT_TRUE(sheet.CssRules()); + ASSERT_EQ(1u, sheet.CssRules()->length()); + CSSStyleRule* style_rule = To<CSSStyleRule>(sheet.CssRules()->item(0)); + CSSStyleDeclaration* style = style_rule->style(); + ASSERT_TRUE(style); + EXPECT_EQ("revert", style->getPropertyValue("top")); + EXPECT_EQ("revert", style->getPropertyValue("--x")); + + // Test setProperty/getPropertyValue: + + DummyExceptionStateForTesting exception_state; + + style->SetPropertyInternal(CSSPropertyID::kLeft, "left", "revert", false, + SecureContextMode::kSecureContext, + exception_state); + style->SetPropertyInternal(CSSPropertyID::kVariable, "--y", " revert", false, + SecureContextMode::kSecureContext, + exception_state); + + EXPECT_EQ("revert", style->getPropertyValue("left")); + EXPECT_EQ("revert", style->getPropertyValue("--y")); + EXPECT_FALSE(exception_state.HadException()); +} + +TEST(CSSStyleDeclarationTest, ParsingRevertWithFeatureDisabled) { + ScopedCSSRevertForTest scoped_revert(false); + + css_test_helpers::TestStyleSheet sheet; + sheet.AddCSSRules("div { top: revert; --x: revert; }"); + ASSERT_TRUE(sheet.CssRules()); + ASSERT_EQ(1u, sheet.CssRules()->length()); + CSSStyleRule* style_rule = To<CSSStyleRule>(sheet.CssRules()->item(0)); + CSSStyleDeclaration* style = style_rule->style(); + ASSERT_TRUE(style); + EXPECT_EQ("", style->getPropertyValue("top")); + EXPECT_EQ(" revert", style->getPropertyValue("--x")); + + // Test setProperty/getPropertyValue: + + DummyExceptionStateForTesting exception_state; + + style->SetPropertyInternal(CSSPropertyID::kLeft, "left", "revert", false, + SecureContextMode::kSecureContext, + exception_state); + style->SetPropertyInternal(CSSPropertyID::kVariable, "--y", " revert", false, + SecureContextMode::kSecureContext, + exception_state); + + EXPECT_EQ("", style->getPropertyValue("left")); + EXPECT_EQ(" revert", style->getPropertyValue("--y")); + EXPECT_FALSE(exception_state.HadException()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_syntax_string_parser.cc b/third_party/blink/renderer/core/css/css_syntax_string_parser.cc index 41c8165..a045ab4 100644 --- a/third_party/blink/renderer/core/css/css_syntax_string_parser.cc +++ b/third_party/blink/renderer/core/css/css_syntax_string_parser.cc
@@ -150,7 +150,6 @@ bool CSSSyntaxStringParser::ConsumeIdent(String& ident) { ident = ConsumeName(input_); - // TODO(crbug.com/579788): Implement 'revert'. // TODO(crbug.com/882285): Make 'default' invalid as <custom-ident>. return !css_property_parser_helpers::IsCSSWideKeyword(ident) && !css_property_parser_helpers::IsRevertKeyword(ident) &&
diff --git a/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc b/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc index 9dc46a5..fc8bf60 100644 --- a/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc +++ b/third_party/blink/renderer/core/css/css_syntax_string_parser_test.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/css/css_syntax_string_parser.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/css/css_syntax_component.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" namespace blink { @@ -118,6 +119,15 @@ EXPECT_FALSE(CSSSyntaxStringParser("initial").Parse()); EXPECT_FALSE(CSSSyntaxStringParser("inherit").Parse()); EXPECT_FALSE(CSSSyntaxStringParser("unset").Parse()); + EXPECT_FALSE(CSSSyntaxStringParser("default").Parse()); + EXPECT_FALSE(CSSSyntaxStringParser("revert").Parse()); + + // 'revert' is forbidden also with CSSRevert toggled. + { + ScopedCSSRevertForTest scoped_revert( + !RuntimeEnabledFeatures::CSSRevertEnabled()); + EXPECT_FALSE(CSSSyntaxStringParser("revert").Parse()); + } } TEST_F(CSSSyntaxStringParserTest, Combinator) {
diff --git a/third_party/blink/renderer/core/css/css_value.cc b/third_party/blink/renderer/core/css/css_value.cc index d849ce27..ed0ac04c 100644 --- a/third_party/blink/renderer/core/css/css_value.cc +++ b/third_party/blink/renderer/core/css/css_value.cc
@@ -65,6 +65,7 @@ #include "third_party/blink/renderer/core/css/css_quad_value.h" #include "third_party/blink/renderer/core/css/css_ray_value.h" #include "third_party/blink/renderer/core/css/css_reflect_value.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" #include "third_party/blink/renderer/core/css/css_shadow_value.h" #include "third_party/blink/renderer/core/css/css_string_value.h" #include "third_party/blink/renderer/core/css/css_timing_function_value.h" @@ -212,6 +213,8 @@ return CompareCSSValues<CSSInitialValue>(*this, other); case kUnsetClass: return CompareCSSValues<cssvalue::CSSUnsetValue>(*this, other); + case kRevertClass: + return CompareCSSValues<cssvalue::CSSRevertValue>(*this, other); case kGridAutoRepeatClass: return CompareCSSValues<cssvalue::CSSGridAutoRepeatValue>(*this, other); case kGridIntegerRepeatClass: @@ -331,6 +334,8 @@ return To<CSSInheritedValue>(this)->CustomCSSText(); case kUnsetClass: return To<cssvalue::CSSUnsetValue>(this)->CustomCSSText(); + case kRevertClass: + return To<cssvalue::CSSRevertValue>(this)->CustomCSSText(); case kInitialClass: return To<CSSInitialValue>(this)->CustomCSSText(); case kGridAutoRepeatClass: @@ -475,6 +480,9 @@ case kUnsetClass: To<cssvalue::CSSUnsetValue>(this)->~CSSUnsetValue(); return; + case kRevertClass: + To<cssvalue::CSSRevertValue>(this)->~CSSRevertValue(); + return; case kGridAutoRepeatClass: To<cssvalue::CSSGridAutoRepeatValue>(this)->~CSSGridAutoRepeatValue(); return; @@ -648,6 +656,9 @@ case kUnsetClass: To<cssvalue::CSSUnsetValue>(this)->TraceAfterDispatch(visitor); return; + case kRevertClass: + To<cssvalue::CSSRevertValue>(this)->TraceAfterDispatch(visitor); + return; case kGridAutoRepeatClass: To<cssvalue::CSSGridAutoRepeatValue>(this)->TraceAfterDispatch(visitor); return;
diff --git a/third_party/blink/renderer/core/css/css_value.h b/third_party/blink/renderer/core/css/css_value.h index db205280..d4bc1ac 100644 --- a/third_party/blink/renderer/core/css/css_value.h +++ b/third_party/blink/renderer/core/css/css_value.h
@@ -109,8 +109,9 @@ bool IsInheritedValue() const { return class_type_ == kInheritedClass; } bool IsInitialValue() const { return class_type_ == kInitialClass; } bool IsUnsetValue() const { return class_type_ == kUnsetClass; } + bool IsRevertValue() const { return class_type_ == kRevertClass; } bool IsCSSWideKeyword() const { - return class_type_ >= kInheritedClass && class_type_ <= kUnsetClass; + return class_type_ >= kInheritedClass && class_type_ <= kRevertClass; } bool IsLayoutFunctionValue() const { return class_type_ == kLayoutFunctionClass; @@ -236,6 +237,7 @@ kInheritedClass, kInitialClass, kUnsetClass, + kRevertClass, kReflectClass, kShadowClass,
diff --git a/third_party/blink/renderer/core/css/css_value_pool.cc b/third_party/blink/renderer/core/css/css_value_pool.cc index 1d62b641..fa730f1 100644 --- a/third_party/blink/renderer/core/css/css_value_pool.cc +++ b/third_party/blink/renderer/core/css/css_value_pool.cc
@@ -45,6 +45,7 @@ : inherited_value_(MakeGarbageCollected<CSSInheritedValue>()), initial_value_(MakeGarbageCollected<CSSInitialValue>()), unset_value_(MakeGarbageCollected<CSSUnsetValue>(PassKey())), + revert_value_(MakeGarbageCollected<CSSRevertValue>(PassKey())), invalid_variable_value_(MakeGarbageCollected<CSSInvalidVariableValue>()), color_transparent_( MakeGarbageCollected<cssvalue::CSSColorValue>(Color::kTransparent)), @@ -62,6 +63,7 @@ visitor->Trace(inherited_value_); visitor->Trace(initial_value_); visitor->Trace(unset_value_); + visitor->Trace(revert_value_); visitor->Trace(invalid_variable_value_); visitor->Trace(color_transparent_); visitor->Trace(color_white_);
diff --git a/third_party/blink/renderer/core/css/css_value_pool.h b/third_party/blink/renderer/core/css/css_value_pool.h index c2fb257..7d978f1c 100644 --- a/third_party/blink/renderer/core/css/css_value_pool.h +++ b/third_party/blink/renderer/core/css/css_value_pool.h
@@ -39,6 +39,7 @@ #include "third_party/blink/renderer/core/css/css_invalid_variable_value.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_property_names.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css_value_keywords.h" @@ -55,6 +56,7 @@ static const int kMaximumCacheableIntegerValue = 255; using CSSColorValue = cssvalue::CSSColorValue; using CSSUnsetValue = cssvalue::CSSUnsetValue; + using CSSRevertValue = cssvalue::CSSRevertValue; using ColorValueCache = HeapHashMap<unsigned, Member<CSSColorValue>>; static const unsigned kMaximumColorCacheSize = 512; using FontFaceValueCache = @@ -71,6 +73,7 @@ CSSInheritedValue* InheritedValue() { return inherited_value_; } CSSInitialValue* InitialValue() { return initial_value_; } CSSUnsetValue* UnsetValue() { return unset_value_; } + CSSRevertValue* RevertValue() { return revert_value_; } CSSInvalidVariableValue* InvalidVariableValue() { return invalid_variable_value_; } @@ -134,6 +137,7 @@ Member<CSSInheritedValue> inherited_value_; Member<CSSInitialValue> initial_value_; Member<CSSUnsetValue> unset_value_; + Member<CSSRevertValue> revert_value_; Member<CSSInvalidVariableValue> invalid_variable_value_; Member<CSSColorValue> color_transparent_; Member<CSSColorValue> color_white_;
diff --git a/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc b/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc index 28df68d1..f7fbef3b 100644 --- a/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc +++ b/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_inherited_value.h" #include "third_party/blink/renderer/core/css/css_initial_value.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/parser/css_property_parser.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -38,6 +39,10 @@ return MakeGarbageCollected<CSSKeywordValue>( getValueName(CSSValueID::kUnset)); } + if (value.IsRevertValue()) { + return MakeGarbageCollected<CSSKeywordValue>( + getValueName(CSSValueID::kRevert)); + } if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { return MakeGarbageCollected<CSSKeywordValue>( getValueName(identifier_value->GetValueID())); @@ -86,6 +91,8 @@ return CSSInitialValue::Create(); case (CSSValueID::kUnset): return cssvalue::CSSUnsetValue::Create(); + case (CSSValueID::kRevert): + return cssvalue::CSSRevertValue::Create(); case (CSSValueID::kInvalid): return MakeGarbageCollected<CSSCustomIdentValue>( AtomicString(keyword_value_));
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc new file mode 100644 index 0000000..25d5c42 --- /dev/null +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_test.cc
@@ -0,0 +1,100 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/cssom/style_property_map.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h" +#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h" +#include "third_party/blink/renderer/core/html/html_element.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" + +namespace blink { + +class StylePropertyMapTest : public PageTestBase {}; + +TEST_F(StylePropertyMapTest, SetRevertWithFeatureEnabled) { + ScopedCSSRevertForTest scoped_revert(true); + + DummyExceptionStateForTesting exception_state; + + HeapVector<CSSStyleValueOrString> revert_string; + revert_string.push_back(CSSStyleValueOrString::FromString(" revert")); + + HeapVector<CSSStyleValueOrString> revert_style_value; + revert_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue( + CSSKeywordValue::Create("revert", exception_state))); + + auto* map = + MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body()); + + map->set(GetDocument().ToExecutionContext(), "top", revert_string, + exception_state); + map->set(GetDocument().ToExecutionContext(), "left", revert_style_value, + exception_state); + + CSSStyleValue* top = + map->get(GetDocument().ToExecutionContext(), "top", exception_state); + CSSStyleValue* left = + map->get(GetDocument().ToExecutionContext(), "left", exception_state); + + ASSERT_TRUE(DynamicTo<CSSKeywordValue>(top)); + EXPECT_EQ(CSSValueID::kRevert, + DynamicTo<CSSKeywordValue>(top)->KeywordValueID()); + + ASSERT_TRUE(DynamicTo<CSSKeywordValue>(left)); + EXPECT_EQ(CSSValueID::kRevert, + DynamicTo<CSSKeywordValue>(top)->KeywordValueID()); + + EXPECT_FALSE(exception_state.HadException()); +} + +TEST_F(StylePropertyMapTest, SetRevertWithFeatureDisabled) { + ScopedCSSRevertForTest scoped_revert(false); + + HeapVector<CSSStyleValueOrString> revert_string; + revert_string.push_back(CSSStyleValueOrString::FromString(" revert")); + + HeapVector<CSSStyleValueOrString> revert_style_value; + + DummyExceptionStateForTesting exception_state; + revert_style_value.push_back(CSSStyleValueOrString::FromCSSStyleValue( + CSSKeywordValue::Create("revert", exception_state))); + EXPECT_FALSE(exception_state.HadException()); + + auto* map = + MakeGarbageCollected<InlineStylePropertyMap>(GetDocument().body()); + + { + DummyExceptionStateForTesting exception_state; + map->set(GetDocument().ToExecutionContext(), "top", revert_string, + exception_state); + EXPECT_TRUE(exception_state.HadException()); + } + { + DummyExceptionStateForTesting exception_state; + map->set(GetDocument().ToExecutionContext(), "left", revert_style_value, + exception_state); + EXPECT_TRUE(exception_state.HadException()); + } + { + DummyExceptionStateForTesting exception_state; + map->set(GetDocument().ToExecutionContext(), "--y", revert_style_value, + exception_state); + EXPECT_TRUE(exception_state.HadException()); + } + + CSSStyleValue* top = + map->get(GetDocument().ToExecutionContext(), "top", exception_state); + CSSStyleValue* left = + map->get(GetDocument().ToExecutionContext(), "left", exception_state); + CSSStyleValue* y = + map->get(GetDocument().ToExecutionContext(), "--y", exception_state); + + EXPECT_FALSE(top); + EXPECT_FALSE(left); + EXPECT_FALSE(y); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/mathml.css b/third_party/blink/renderer/core/css/mathml.css index 5adc7b1..b1ea4c50 100644 --- a/third_party/blink/renderer/core/css/mathml.css +++ b/third_party/blink/renderer/core/css/mathml.css
@@ -46,7 +46,7 @@ outline: auto 1px -webkit-focus-ring-color; } -maction, merror, mfrac, mphantom, mrow, mspace, mstyle +maction, merror, mfrac, mphantom, mrow, mspace, mstyle, munder, mover, munderover { display: math; }
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc index faf3e61..5b0119f 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/core/css/css_initial_value.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/parser/css_parser_idioms.h" #include "third_party/blink/renderer/core/css/parser/css_property_parser.h" @@ -793,7 +794,7 @@ return (value_id >= CSSValueID::kDrag && value_id <= CSSValueID::kNoDrag) || value_id == CSSValueID::kNone; - case CSSPropertyID::kWebkitAppearance: + case CSSPropertyID::kAppearance: return (value_id >= CSSValueID::kCheckbox && value_id <= CSSValueID::kTextarea) || value_id == CSSValueID::kNone || value_id == CSSValueID::kAuto; @@ -1049,7 +1050,6 @@ case CSSPropertyID::kVectorEffect: case CSSPropertyID::kVisibility: case CSSPropertyID::kWebkitAppRegion: - case CSSPropertyID::kWebkitAppearance: case CSSPropertyID::kBackfaceVisibility: case CSSPropertyID::kBorderBlockEndStyle: case CSSPropertyID::kBorderBlockStartStyle: @@ -1107,13 +1107,15 @@ DCHECK(!string.IsEmpty()); if (!CSSParserFastPaths::IsKeywordPropertyID(property_id)) { - // All properties accept the values of "initial," "inherit" and "unset". + // All properties accept CSS-wide keywords. if (!EqualIgnoringASCIICase(string, "initial") && !EqualIgnoringASCIICase(string, "inherit") && - !EqualIgnoringASCIICase(string, "unset")) + !EqualIgnoringASCIICase(string, "unset") && + (!RuntimeEnabledFeatures::CSSRevertEnabled() || + !EqualIgnoringASCIICase(string, "revert"))) return nullptr; - // Parse initial/inherit/unset shorthands using the CSSPropertyParser. + // Parse CSS-wide keyword shorthands using the CSSPropertyParser. if (shorthandForProperty(property_id).length()) return nullptr; @@ -1133,6 +1135,10 @@ return CSSInitialValue::Create(); if (value_id == CSSValueID::kUnset) return cssvalue::CSSUnsetValue::Create(); + if (RuntimeEnabledFeatures::CSSRevertEnabled() && + value_id == CSSValueID::kRevert) { + return cssvalue::CSSRevertValue::Create(); + } if (CSSParserFastPaths::IsValidKeywordPropertyAndValue(property_id, value_id, parser_mode)) return CSSIdentifierValue::Create(value_id);
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc index 5d01a442..a54b79c 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_fast_paths_test.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/css/css_color_value.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" namespace blink { @@ -53,6 +54,46 @@ ASSERT_EQ(nullptr, value); } +TEST(CSSParserFastPathsTest, ParseRevert) { + // Revert enabled, IsKeywordPropertyID=false + { + DCHECK(!CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kMarginTop)); + ScopedCSSRevertForTest scoped_revert(true); + CSSValue* value = CSSParserFastPaths::MaybeParseValue( + CSSPropertyID::kMarginTop, "revert", kHTMLStandardMode); + ASSERT_TRUE(value); + EXPECT_TRUE(value->IsRevertValue()); + } + + // Revert enabled, IsKeywordPropertyID=true + { + DCHECK(CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kDisplay)); + ScopedCSSRevertForTest scoped_revert(true); + CSSValue* value = CSSParserFastPaths::MaybeParseValue( + CSSPropertyID::kDisplay, "revert", kHTMLStandardMode); + ASSERT_TRUE(value); + EXPECT_TRUE(value->IsRevertValue()); + } + + // Revert disabled, IsKeywordPropertyID=false + { + DCHECK(!CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kMarginTop)); + ScopedCSSRevertForTest scoped_revert(false); + CSSValue* value = CSSParserFastPaths::MaybeParseValue( + CSSPropertyID::kMarginTop, "revert", kHTMLStandardMode); + EXPECT_FALSE(value); + } + + // Revert disabled, IsKeywordPropertyID=true + { + DCHECK(CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID::kDisplay)); + ScopedCSSRevertForTest scoped_revert(false); + CSSValue* value = CSSParserFastPaths::MaybeParseValue( + CSSPropertyID::kDisplay, "revert", kHTMLStandardMode); + EXPECT_FALSE(value); + } +} + TEST(CSSParserFastPathsTest, ParseTransform) { CSSValue* value = CSSParserFastPaths::MaybeParseValue( CSSPropertyID::kTransform, "translate(5.5px, 5px)", kHTMLStandardMode);
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser.cc b/third_party/blink/renderer/core/css/parser/css_property_parser.cc index 1365fb4..b7d3024 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_property_parser.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/css/css_inherited_value.h" #include "third_party/blink/renderer/core/css/css_initial_value.h" #include "third_party/blink/renderer/core/css/css_pending_substitution_value.h" +#include "third_party/blink/renderer/core/css/css_revert_value.h" #include "third_party/blink/renderer/core/css/css_unicode_range_value.h" #include "third_party/blink/renderer/core/css/css_unset_value.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" @@ -45,6 +46,8 @@ value = CSSInheritedValue::Create(); if (id == CSSValueID::kUnset) value = cssvalue::CSSUnsetValue::Create(); + if (RuntimeEnabledFeatures::CSSRevertEnabled() && id == CSSValueID::kRevert) + value = cssvalue::CSSRevertValue::Create(); if (value) range = local_range;
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc index c2034ea..b194927 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
@@ -29,7 +29,9 @@ #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/properties/longhand.h" #include "third_party/blink/renderer/core/css/style_color.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/web_feature.h" +#include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/style_property_shorthand.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" @@ -468,18 +470,9 @@ bool CanConsumeCalcValue(CalculationCategory category, CSSParserMode css_parser_mode) { - if (category == kCalcLength || category == kCalcPercent || - category == kCalcPercentLength) - return true; - - if (css_parser_mode != kSVGAttributeMode) - return false; - - if (category == kCalcNumber || category == kCalcPercentNumber || - category == kCalcLengthNumber || category == kCalcPercentLengthNumber) - return true; - - return false; + return category == kCalcLength || category == kCalcPercent || + category == kCalcPercentLength || + (css_parser_mode == kSVGAttributeMode && category == kCalcNumber); } CSSPrimitiveValue* ConsumeLengthOrPercent(CSSParserTokenRange& range, @@ -510,16 +503,7 @@ value->GetDoubleValue() != 0; } const auto& math_value = To<CSSMathFunctionValue>(*value); - switch (math_value.Category()) { - case kCalcNumber: - return math_value.DoubleValue() != 0; - case kCalcPercentNumber: - case kCalcLengthNumber: - case kCalcPercentLengthNumber: - return true; - default: - return false; - } + return math_value.Category() == kCalcNumber && math_value.DoubleValue() != 0; } } // namespace @@ -659,8 +643,6 @@ if (EqualIgnoringASCIICase(token.Value(), "default")) context.Count(WebFeature::kDefaultInCustomIdent); - if (EqualIgnoringASCIICase(token.Value(), "revert")) - context.Count(WebFeature::kRevertInCustomIdent); return MakeGarbageCollected<CSSCustomIdentValue>( token.Value().ToAtomicString()); @@ -1868,7 +1850,9 @@ bool IsCSSWideKeyword(StringView keyword) { return EqualIgnoringASCIICase(keyword, "initial") || EqualIgnoringASCIICase(keyword, "inherit") || - EqualIgnoringASCIICase(keyword, "unset"); + EqualIgnoringASCIICase(keyword, "unset") || + (RuntimeEnabledFeatures::CSSRevertEnabled() && + EqualIgnoringASCIICase(keyword, "revert")); } // https://drafts.csswg.org/css-cascade/#default @@ -1952,7 +1936,30 @@ if (!context.IsUseCounterRecordingEnabled()) return; switch (property) { - case CSSPropertyID::kWebkitAppearance: { + case CSSPropertyID::kAppearance: + if (value_id == CSSValueID::kInnerSpinButton || + value_id == CSSValueID::kMediaSlider || + value_id == CSSValueID::kMediaSliderthumb || + value_id == CSSValueID::kMediaVolumeSlider || + value_id == CSSValueID::kMediaVolumeSliderthumb || + value_id == CSSValueID::kSliderVertical || + value_id == CSSValueID::kSliderthumbHorizontal || + value_id == CSSValueID::kSliderthumbVertical || + value_id == CSSValueID::kSearchfieldCancelButton) { + if (const auto* document = context.GetDocument()) { + document->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kOther, + mojom::blink::ConsoleMessageLevel::kWarning, + String("The keyword '") + getValueName(value_id) + + "' specified to an 'appearance' property is not " + "standardized. It will be removed in the future.")); + } + } + FALLTHROUGH; + // This function distinguishes 'appearance' and '-webkit-appearance' + // though other property aliases are handles as their aliased properties. + // See Appearance::ParseSingleValue(). + case CSSPropertyID::kAliasWebkitAppearance: { WebFeature feature; if (value_id == CSSValueID::kNone) { feature = WebFeature::kCSSValueAppearanceNone;
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h index 45c628c..6c4ea21 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h
@@ -150,7 +150,8 @@ CSSValue* ConsumeAxis(CSSParserTokenRange&, const CSSParserContext& context); -bool IsCSSWideKeyword(StringView); +// See also css_parsing_utils::IsCSSWideKeyword. +CORE_EXPORT bool IsCSSWideKeyword(StringView); bool IsRevertKeyword(StringView); bool IsDefaultKeyword(StringView);
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc new file mode 100644 index 0000000..2eb068a --- /dev/null +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers_test.cc
@@ -0,0 +1,25 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +TEST(CSSPropertyParserHelpersTest, ParseRevert) { + { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_TRUE(css_property_parser_helpers::IsCSSWideKeyword("revert")); + } + + { + ScopedCSSRevertForTest scoped_revert(false); + EXPECT_FALSE(css_property_parser_helpers::IsCSSWideKeyword("revert")); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc index edd37e2..0d39231 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
@@ -638,20 +638,6 @@ EXPECT_TRUE(IsCounted(feature)); } -TEST_F(CSSPropertyUseCounterTest, CSSPropertyRevertAnimationNameUseCount) { - WebFeature feature = WebFeature::kRevertInCustomIdent; - EXPECT_FALSE(IsCounted(feature)); - - ParseProperty(CSSPropertyID::kAnimationName, "initial"); - EXPECT_FALSE(IsCounted(feature)); - - ParseProperty(CSSPropertyID::kAnimationName, "test"); - EXPECT_FALSE(IsCounted(feature)); - - ParseProperty(CSSPropertyID::kAnimationName, "revert"); - EXPECT_TRUE(IsCounted(feature)); -} - TEST_F(CSSPropertyUseCounterTest, CSSPropertyContainStyleUseCount) { WebFeature feature = WebFeature::kCSSValueContainStyle; EXPECT_FALSE(IsCounted(feature)); @@ -725,4 +711,28 @@ value->CssText()); } +TEST(CSSPropertyParserTest, ParseRevert) { + auto* context = MakeGarbageCollected<CSSParserContext>( + kHTMLStandardMode, SecureContextMode::kInsecureContext); + + String string = " revert"; + CSSTokenizer tokenizer(string); + const auto tokens = tokenizer.TokenizeToEOF(); + + { + ScopedCSSRevertForTest scoped_revert(true); + const CSSValue* value = CSSPropertyParser::ParseSingleValue( + CSSPropertyID::kMarginLeft, CSSParserTokenRange(tokens), context); + ASSERT_TRUE(value); + EXPECT_TRUE(value->IsRevertValue()); + } + + { + ScopedCSSRevertForTest scoped_revert(false); + const CSSValue* value = CSSPropertyParser::ParseSingleValue( + CSSPropertyID::kMarginLeft, CSSParserTokenRange(tokens), context); + EXPECT_FALSE(value); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_variable_parser.cc b/third_party/blink/renderer/core/css/parser/css_variable_parser.cc index 61a8c02..d95059d9 100644 --- a/third_party/blink/renderer/core/css/parser/css_variable_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_variable_parser.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h" +#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -114,9 +115,7 @@ range.ConsumeWhitespace(); if (range.Peek().GetType() == kIdentToken) { CSSValueID id = range.ConsumeIncludingWhitespace().Id(); - if (range.AtEnd() && - (id == CSSValueID::kInherit || id == CSSValueID::kInitial || - id == CSSValueID::kUnset)) + if (range.AtEnd() && css_parsing_utils::IsCSSWideKeyword(id)) return id; }
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 4ede24d..c2e3c3a 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -458,6 +458,13 @@ return IsContentPositionKeyword(id) || IsLeftOrRightKeyword(id); } +bool IsCSSWideKeyword(CSSValueID id) { + return id == CSSValueID::kInherit || id == CSSValueID::kInitial || + id == CSSValueID::kUnset || + (RuntimeEnabledFeatures::CSSRevertEnabled() && + (id == CSSValueID::kRevert)); +} + CSSValue* ConsumeScrollOffset(CSSParserTokenRange& range, const CSSParserContext& context) { range.ConsumeWhitespace();
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h index 1ffeb84..6cf2745 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.h +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_CSS_PARSING_UTILS_H_ +#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h" @@ -46,6 +47,7 @@ bool IsSelfPositionOrLeftOrRightKeyword(CSSValueID); bool IsContentPositionKeyword(CSSValueID); bool IsContentPositionOrLeftOrRightKeyword(CSSValueID); +CORE_EXPORT bool IsCSSWideKeyword(CSSValueID); CSSValue* ConsumeScrollOffset(CSSParserTokenRange&, const CSSParserContext&); CSSValue* ConsumeSelfPositionOverflowPosition(CSSParserTokenRange&,
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc index 8ac05ca..3e768f51 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/core/html/html_html_element.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" +#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" namespace blink { @@ -21,4 +22,16 @@ EXPECT_TRUE(document.IsUseCounted(feature)); } +TEST(CSSParsingUtilsTest, Revert) { + { + ScopedCSSRevertForTest scoped_revert(true); + EXPECT_TRUE(css_parsing_utils::IsCSSWideKeyword(CSSValueID::kRevert)); + } + + { + ScopedCSSRevertForTest scoped_revert(false); + EXPECT_FALSE(css_parsing_utils::IsCSSWideKeyword(CSSValueID::kRevert)); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index 2273c25..700ce58f 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_value_pair.h" #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" +#include "third_party/blink/renderer/core/css/parser/css_parser_fast_paths.h" #include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h" #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h" #include "third_party/blink/renderer/core/css/parser/css_parser_token.h" @@ -6834,7 +6835,24 @@ state.GetDocument().SetHasAnnotatedRegions(true); } -const CSSValue* WebkitAppearance::CSSValueFromComputedStyleInternal( +const CSSValue* Appearance::ParseSingleValue( + CSSParserTokenRange& range, + const CSSParserContext& context, + const CSSParserLocalContext& local_context) const { + CSSValueID id = range.Peek().Id(); + CSSPropertyID property = CSSPropertyID::kAppearance; + if (CSSParserFastPaths::IsValidKeywordPropertyAndValue(property, id, + context.Mode())) { + if (local_context.UseAliasParsing()) + property = CSSPropertyID::kAliasWebkitAppearance; + css_property_parser_helpers::CountKeywordOnlyPropertyUsage(property, + context, id); + return css_property_parser_helpers::ConsumeIdent(range); + } + return nullptr; +} + +const CSSValue* Appearance::CSSValueFromComputedStyleInternal( const ComputedStyle& style, const SVGComputedStyle&, const LayoutObject*,
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc index c38edab6..8b06d79c 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -129,8 +129,8 @@ ApplyMatchResult(resolver); ApplyInterpolations(resolver); - if (map_.Find(CSSPropertyName(CSSPropertyID::kWebkitAppearance)) && - !resolver.filter_.Rejects(GetCSSPropertyWebkitAppearance()) && + if (map_.Find(CSSPropertyName(CSSPropertyID::kAppearance)) && + !resolver.filter_.Rejects(GetCSSPropertyAppearance()) && state_.Style()->HasAppearance()) { state_.Style()->SetHasAuthorBackground(HasAuthorBackground()); state_.Style()->SetHasAuthorBorder(HasAuthorBorder()); @@ -501,6 +501,9 @@ return ResolveVariableReference(property, *v, resolver); if (const auto* v = DynamicTo<cssvalue::CSSPendingSubstitutionValue>(value)) return ResolvePendingSubstitution(property, *v, resolver); + // TODO(andruud): Actually revert instead of treating as unset. + if (value.IsRevertValue()) + return cssvalue::CSSUnsetValue::Create(); return &value; }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index ef44c779..b5cf9632 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -7238,7 +7238,7 @@ } void Document::AddConsoleMessage(ConsoleMessage* message, - bool discard_duplicates) { + bool discard_duplicates) const { // Don't let non-attached Documents spam the console. if (domWindow()) domWindow()->AddConsoleMessage(message, discard_duplicates);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index b13f3c3..f8c96c1 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -680,6 +680,9 @@ kRunPostLayoutTasksSynchronously, }; void UpdateStyleAndLayoutForNode(const Node*, DocumentUpdateReason); + void IncLayoutCallsCounter() { ++layout_calls_counter_; } + void IncLayoutCallsCounterNG() { ++layout_calls_counter_ng_; } + scoped_refptr<const ComputedStyle> StyleForPage(int page_index); // Ensures that location-based data will be valid for a given node. @@ -1451,7 +1454,7 @@ void DidAssociateFormControl(Element*); void AddConsoleMessage(ConsoleMessage* message, - bool discard_duplicates = false); + bool discard_duplicates = false) const; void AddInspectorIssue(InspectorIssue*); LocalFrame* ExecutingFrame(); @@ -2253,6 +2256,13 @@ // The number of canvas elements on the document int num_canvases_ = 0; + // The number of LayoutObject::UpdateLayout() calls for both of the legacy + // layout and LayoutNG. + uint32_t layout_calls_counter_ = 0; + + // The number of LayoutObject::UpdateLayout() calls for LayoutNG. + uint32_t layout_calls_counter_ng_ = 0; + // Number of display locks in this document that block all activation. int display_lock_blocking_all_activation_count_ = 0; // Number of locked display locks in the document.
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn index cb2f84eb..e9cb636 100644 --- a/third_party/blink/renderer/core/layout/BUILD.gn +++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -427,6 +427,8 @@ "ng/mathml/ng_math_row_layout_algorithm.h", "ng/mathml/ng_math_space_layout_algorithm.cc", "ng/mathml/ng_math_space_layout_algorithm.h", + "ng/mathml/ng_math_under_over_layout_algorithm.cc", + "ng/mathml/ng_math_under_over_layout_algorithm.h", "ng/ng_absolute_utils.cc", "ng/ng_absolute_utils.h", "ng/ng_block_break_token.cc",
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index d10c1623..b155d33 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -296,8 +296,13 @@ ShapeOutsideInfo::RemoveInfo(*this); if (!DocumentBeingDestroyed()) { - if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) - first_inline_fragment->LayoutObjectWillBeDestroyed(); + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) + first_inline_fragment->LayoutObjectWillBeDestroyed(); + } else if (FirstInlineFragmentItemIndex()) { + NGFragmentItems::LayoutObjectWillBeDestroyed(*this); + ClearFirstInlineFragmentItemIndex(); + } for (auto result : layout_results_) result->PhysicalFragment().LayoutObjectWillBeDestroyed(); } @@ -886,6 +891,11 @@ // Legacy, then NG again, NG won't use a stale layout result. if (IsOutOfFlowPositioned() && !IsLayoutNGObject()) ClearLayoutResults(); + + Document& document = GetDocument(); + document.IncLayoutCallsCounter(); + if (IsLayoutNGObject()) + document.IncLayoutCallsCounterNG(); } bool LayoutBox::HasOverrideIntrinsicContentWidth() const { @@ -2468,17 +2478,12 @@ return inline_box_wrapper_; if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) return first_paint_fragment_; - // TODO(yosin): We should use |first_fragment_item_index_|. - NGInlineCursor cursor; - cursor.MoveTo(*this); - return cursor; + return first_fragment_item_index_; } void LayoutBox::SetFirstInlineFragment(NGPaintFragment* fragment) { CHECK(IsInLayoutNGInlineFormattingContext()) << *this; - // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of - // |!fragment|. - DCHECK(!fragment || !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); + DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_paint_fragment_ = fragment; } @@ -2492,17 +2497,26 @@ CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK_NE(index, 0u); - // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|, - // we should enable below. - // first_fragment_item_index_ = index; + first_fragment_item_index_ = index; } void LayoutBox::InLayoutNGInlineFormattingContextWillChange(bool new_value) { - DeleteLineBoxWrapper(); + if (IsInLayoutNGInlineFormattingContext()) { + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + SetFirstInlineFragment(nullptr); + } else { + ClearFirstInlineFragmentItemIndex(); + } + } else { + DeleteLineBoxWrapper(); + } // Because |first_paint_fragment_| and |inline_box_wrapper_| are union, when // one is deleted, the other should be initialized to nullptr. - DCHECK(new_value ? !first_paint_fragment_ : !inline_box_wrapper_); + DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled() + ? !first_fragment_item_index_ + : !first_paint_fragment_) + : !inline_box_wrapper_); } void LayoutBox::SetCachedLayoutResult( @@ -2524,11 +2538,40 @@ void LayoutBox::AddLayoutResult(scoped_refptr<const NGLayoutResult> result, wtf_size_t index) { DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess); - if (index != WTF::kNotFound) - ShrinkLayoutResults(index); + if (index != WTF::kNotFound && layout_results_.size() > index) { + if (layout_results_.size() > index + 1) + ShrinkLayoutResults(index + 1); + ReplaceLayoutResult(std::move(result), index); + return; + } + if (!index) { + if (const NGFragmentItems* items = + To<NGPhysicalBoxFragment>(result->PhysicalFragment()).Items()) + items->AssociateWithLayoutObject(); + } layout_results_.push_back(std::move(result)); } +void LayoutBox::ReplaceLayoutResult(scoped_refptr<const NGLayoutResult> result, + wtf_size_t index) { + DCHECK_LE(index, layout_results_.size()); + const NGLayoutResult* old_result = layout_results_[index].get(); + if (old_result == result.get()) + return; + if (!index && + &old_result->PhysicalFragment() != &result->PhysicalFragment()) { + if (const NGFragmentItems* old_items = + To<NGPhysicalBoxFragment>(old_result->PhysicalFragment()).Items()) { + InvalidateItems(*old_result); + old_items->ClearAssociatedFragments(); + } + if (const NGFragmentItems* new_items = + To<NGPhysicalBoxFragment>(result->PhysicalFragment()).Items()) + new_items->AssociateWithLayoutObject(); + } + layout_results_[index] = std::move(result); +} + void LayoutBox::ClearLayoutResults() { if (measure_result_) InvalidateItems(*measure_result_); @@ -2542,6 +2585,13 @@ // Invalidate if inline |DisplayItemClient|s will be destroyed. for (wtf_size_t i = results_to_keep; i < layout_results_.size(); i++) InvalidateItems(*layout_results_[i]); + if (results_to_keep == 0 && !layout_results_.IsEmpty()) { + if (const NGFragmentItems* old_items = + To<NGPhysicalBoxFragment>(layout_results_[0]->PhysicalFragment()) + .Items()) { + old_items->ClearAssociatedFragments(); + } + } layout_results_.Shrink(results_to_keep); } @@ -2563,6 +2613,7 @@ const NGLayoutResult* result = layout_results_[0].get(); if (result->IsSingleUse()) return nullptr; + DCHECK(result->PhysicalFragment().IsAlive()); DCHECK_EQ(layout_results_.size(), 1u); return result; }
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index a9484751..f0aa953 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -969,6 +969,8 @@ // Store one layout result (with its physical fragment) at the specified // index, and delete all entries following it. void AddLayoutResult(scoped_refptr<const NGLayoutResult>, wtf_size_t index); + void ReplaceLayoutResult(scoped_refptr<const NGLayoutResult>, + wtf_size_t index); void ShrinkLayoutResults(wtf_size_t results_to_keep); void ClearLayoutResults(); @@ -2001,11 +2003,10 @@ inline NGPaintFragment* LayoutBox::FirstInlineFragment() const { if (!IsInLayoutNGInlineFormattingContext()) return nullptr; - // TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to - // |NGInlineCursor|, we should change this to |DCHECK()|. - if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) - return nullptr; - return first_paint_fragment_; + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return first_paint_fragment_; + NOTREACHED(); + return nullptr; } inline wtf_size_t LayoutBox::FirstInlineFragmentItemIndex() const {
diff --git a/third_party/blink/renderer/core/layout/layout_button.cc b/third_party/blink/renderer/core/layout/layout_button.cc index 28d3a96..29ddba1 100644 --- a/third_party/blink/renderer/core/layout/layout_button.cc +++ b/third_party/blink/renderer/core/layout/layout_button.cc
@@ -20,6 +20,8 @@ #include "third_party/blink/renderer/core/layout/layout_button.h" +#include "third_party/blink/renderer/core/frame/web_feature.h" + namespace blink { LayoutButton::LayoutButton(Element* element) @@ -94,8 +96,12 @@ return MarginRight() + Size().Width() - BorderLeft() - PaddingLeft() - VerticalScrollbarWidth(); } - return LayoutFlexibleBox::BaselinePosition(baseline, first_line, direction, - line_position_mode); + LayoutUnit result_baseline = LayoutFlexibleBox::BaselinePosition( + baseline, first_line, direction, line_position_mode); + LayoutUnit correct_baseline = LayoutBlock::InlineBlockBaseline(direction); + if (correct_baseline != result_baseline) + UseCounter::Count(GetDocument(), WebFeature::kWrongBaselineOfButtonElement); + return result_baseline; } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index a7dd0e5..57acf1f3 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -136,10 +136,15 @@ box->Remove(); } } else { - if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) - first_inline_fragment->LayoutObjectWillBeDestroyed(); if (Parent()) Parent()->DirtyLinesFromChangedChild(this); + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) + first_inline_fragment->LayoutObjectWillBeDestroyed(); + } else if (FirstInlineFragmentItemIndex()) { + NGFragmentItems::LayoutObjectWillBeDestroyed(*this); + ClearFirstInlineFragmentItemIndex(); + } } } @@ -155,9 +160,7 @@ void LayoutInline::SetFirstInlineFragment(NGPaintFragment* fragment) { CHECK(IsInLayoutNGInlineFormattingContext()) << *this; - // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of - // |!fragment|. - DCHECK(!fragment || !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); + DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_paint_fragment_ = fragment; } @@ -171,9 +174,7 @@ CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK_NE(index, 0u); - // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|, - // we should enable below. - // first_fragment_item_index_ = index; + first_fragment_item_index_ = index; } bool LayoutInline::HasInlineFragments() const { @@ -181,18 +182,26 @@ return FirstLineBox(); if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) return first_paint_fragment_; - // TODO(yosin): We should use |first_fragment_item_index_|. - NGInlineCursor cursor; - cursor.MoveTo(*this); - return cursor; + return first_fragment_item_index_; } void LayoutInline::InLayoutNGInlineFormattingContextWillChange(bool new_value) { - DeleteLineBoxes(); + if (IsInLayoutNGInlineFormattingContext()) { + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + SetFirstInlineFragment(nullptr); + } else { + ClearFirstInlineFragmentItemIndex(); + } + } else { + DeleteLineBoxes(); + } // Because |first_paint_fragment_| and |line_boxes_| are union, when one is // deleted, the other should be initialized to nullptr. - DCHECK(new_value ? !first_paint_fragment_ : !line_boxes_.First()); + DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled() + ? !first_fragment_item_index_ + : !first_paint_fragment_) + : !line_boxes_.First()); } LayoutInline* LayoutInline::InlineElementContinuation() const {
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h index 448bf29ca..771303d 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.h +++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -429,6 +429,7 @@ return nullptr; // TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to // |NGInlineCursor|, we should change this to |DCHECK()|. + DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) return nullptr; return first_paint_fragment_;
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 714d124..3e65542 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -3490,7 +3490,11 @@ if (IsInLayoutNGInlineFormattingContext() == new_value) return; InLayoutNGInlineFormattingContextWillChange(new_value); + // The association cache for inline fragments is in union. Make sure the + // cache is cleared before and after changing this flag. + DCHECK(!HasInlineFragments()); bitfields_.SetIsInLayoutNGInlineFormattingContext(new_value); + DCHECK(!HasInlineFragments()); } inline void LayoutObject::SetHasBoxDecorationBackground(bool b) {
diff --git a/third_party/blink/renderer/core/layout/layout_object_child_list.cc b/third_party/blink/renderer/core/layout/layout_object_child_list.cc index 8a71bc3..63b241f3 100644 --- a/third_party/blink/renderer/core/layout/layout_object_child_list.cc +++ b/third_party/blink/renderer/core/layout/layout_object_child_list.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_view.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h" #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h" #include "third_party/blink/renderer/core/paint/object_paint_invalidator.h" @@ -59,9 +60,13 @@ } if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { - // TODO(yosin): Tells |NGFragmentItem| about they become not to associate - // to layout object. - object->ClearFirstInlineFragmentItemIndex(); + // This LayoutObject is not technically destroyed, but further access should + // be prohibited when moved to different parent as if it were destroyed. + if (object->FirstInlineFragmentItemIndex()) { + if (auto* text = ToLayoutTextOrNull(object)) + text->DetachAbstractInlineTextBoxesIfNeeded(); + NGFragmentItems::LayoutObjectWillBeMoved(*object); + } } else if (NGPaintFragment* fragment = object->FirstInlineFragment()) { // This LayoutObject is not technically destroyed, but further access should // be prohibited when moved to different parent as if it were destroyed.
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index b1ccf91..cc5509c2 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -153,10 +153,14 @@ LayoutText::~LayoutText() { #if DCHECK_IS_ON() - if (IsInLayoutNGInlineFormattingContext()) - DCHECK(!first_paint_fragment_); - else + if (IsInLayoutNGInlineFormattingContext()) { + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + DCHECK(!first_paint_fragment_); + else + DCHECK(!first_fragment_item_index_); + } else { text_boxes_.AssertIsEmpty(); + } #endif } @@ -223,20 +227,26 @@ for (InlineTextBox* box : TextBoxes()) box->Remove(); } else { + if (Parent()) + Parent()->DirtyLinesFromChangedChild(this); if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { - if (has_abstract_inline_text_box_) + if (FirstInlineFragmentItemIndex()) { + DetachAbstractInlineTextBoxesIfNeeded(); + NGFragmentItems::LayoutObjectWillBeDestroyed(*this); ClearFirstInlineFragmentItemIndex(); + } } else if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) { first_inline_fragment->LayoutObjectWillBeDestroyed(); SetFirstInlineFragment(nullptr); } - if (Parent()) - Parent()->DirtyLinesFromChangedChild(this); } } else if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { - if (has_abstract_inline_text_box_) + if (FirstInlineFragmentItemIndex()) { + DetachAbstractInlineTextBoxesIfNeeded(); + NGFragmentItems::LayoutObjectWillBeDestroyed(*this); ClearFirstInlineFragmentItemIndex(); + } } else if (NGPaintFragment* first_inline_fragment = FirstInlineFragment()) { // Still do this to clear the global hash map in NGAbstractInlineTextBox. SetFirstInlineFragment(nullptr); @@ -298,10 +308,7 @@ void LayoutText::SetFirstInlineFragment(NGPaintFragment* first_fragment) { CHECK(IsInLayoutNGInlineFormattingContext()); - // TODO(yosin): Once we remove |NGPaintFragment|, we should get rid of - // |!fragment|. - DCHECK(!first_fragment || - !RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); + DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DetachAbstractInlineTextBoxesIfNeeded(); first_paint_fragment_ = first_fragment; } @@ -319,17 +326,26 @@ DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK_NE(index, 0u); DetachAbstractInlineTextBoxesIfNeeded(); - // TDOO(yosin): Once we update all |LayoutObject::FirstInlineFragment()|, - // we should enable below. - // first_fragment_item_index_ = index; + first_fragment_item_index_ = index; } void LayoutText::InLayoutNGInlineFormattingContextWillChange(bool new_value) { - DeleteTextBoxes(); + if (IsInLayoutNGInlineFormattingContext()) { + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + SetFirstInlineFragment(nullptr); + } else { + ClearFirstInlineFragmentItemIndex(); + } + } else { + DeleteTextBoxes(); + } // Because |first_paint_fragment_| and |text_boxes_| are union, when one is // deleted, the other should be initialized to nullptr. - DCHECK(new_value ? !first_paint_fragment_ : !text_boxes_.First()); + DCHECK(new_value ? (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled() + ? !first_fragment_item_index_ + : !first_paint_fragment_) + : !text_boxes_.First()); // Because there are no inline boxes associated to this text, we should not // have abstract inline text boxes too. @@ -414,11 +430,11 @@ } bool LayoutText::HasInlineFragments() const { - if (IsInLayoutNGInlineFormattingContext()) { - NGInlineCursor cursor; - cursor.MoveTo(*this); - return cursor.IsNotNull(); - } + if (IsInLayoutNGInlineFormattingContext()) { + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return first_paint_fragment_; + return first_fragment_item_index_; + } return FirstTextBox(); }
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h index 17ca490..42b67a90 100644 --- a/third_party/blink/renderer/core/layout/layout_text.h +++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -476,11 +476,10 @@ inline NGPaintFragment* LayoutText::FirstInlineFragment() const { if (!IsInLayoutNGInlineFormattingContext()) return nullptr; - // TODO(yosin): Once we replace all usage of |FirstInlineFragment()| to - // |NGInlineCursor|, we should change this to |DCHECK()|. - if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) - return nullptr; - return first_paint_fragment_; + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + return first_paint_fragment_; + NOTREACHED(); + return nullptr; } inline wtf_size_t LayoutText::FirstInlineFragmentItemIndex() const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc index 63a23df..f5e29f8ef 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -174,6 +174,21 @@ return false; } +void NGFragmentItem::LayoutObjectWillBeDestroyed() const { + const_cast<NGFragmentItem*>(this)->layout_object_ = nullptr; + if (const NGPhysicalBoxFragment* fragment = BoxFragment()) + fragment->LayoutObjectWillBeDestroyed(); +} + +void NGFragmentItem::LayoutObjectWillBeMoved() const { + // When |Layoutobject| is moved out from the current IFC, we should not clear + // the association with it in |ClearAssociatedFragments|, because the + // |LayoutObject| may be moved to a different IFC and is already laid out + // before clearing this IFC. This happens e.g., when split inlines moves + // inline children into a child anonymous block. + const_cast<NGFragmentItem*>(this)->layout_object_ = nullptr; +} + inline const LayoutBox* NGFragmentItem::InkOverflowOwnerBox() const { if (Type() == kBox) return ToLayoutBoxOrNull(GetLayoutObject());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h index c07af90..c9eeea8c 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -117,6 +117,8 @@ LayoutObject* GetMutableLayoutObject() const { return const_cast<LayoutObject*>(layout_object_); } + void LayoutObjectWillBeDestroyed() const; + void LayoutObjectWillBeMoved() const; Node* GetNode() const { return layout_object_->GetNode(); } Node* NodeForHitTest() const { return layout_object_->NodeForHitTest(); } bool IsSiblingOf(const NGFragmentItem& other) const;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc index 794995b..33afc917 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -5,17 +5,28 @@ #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h" namespace blink { +namespace { + +inline bool ShouldAssociateWithLayoutObject(const NGFragmentItem& item) { + return item.Type() != NGFragmentItem::kLine && !item.IsFloating(); +} + +} // namespace + NGFragmentItems::NGFragmentItems(NGFragmentItemsBuilder* builder) : items_(std::move(builder->items_)), text_content_(std::move(builder->text_content_)), first_line_text_content_(std::move(builder->first_line_text_content_)) {} -// static -void NGFragmentItems::AssociateWithLayoutObject( - Vector<std::unique_ptr<NGFragmentItem>>* items) { +void NGFragmentItems::AssociateWithLayoutObject() const { + const Vector<std::unique_ptr<NGFragmentItem>>* items = &items_; + DCHECK(std::all_of(items->begin(), items->end(), [](const auto& item) { + return !item->DeltaToNextForSameLayoutObject(); + })); // items_[0] can be: // - kBox for list marker, e.g. <li>abc</li> // - kLine for line, e.g. <div>abc</div> @@ -26,12 +37,13 @@ HashMap<const LayoutObject*, wtf_size_t> last_fragment_map; for (wtf_size_t index = 1u; index < items->size(); ++index) { const NGFragmentItem& item = *(*items)[index]; - if (item.Type() == NGFragmentItem::kLine) + if (!ShouldAssociateWithLayoutObject(item)) continue; LayoutObject* const layout_object = item.GetMutableLayoutObject(); DCHECK(layout_object->IsInLayoutNGInlineFormattingContext()) << item; auto insert_result = last_fragment_map.insert(layout_object, index); if (insert_result.is_new_entry) { + DCHECK_EQ(layout_object->FirstInlineFragmentItemIndex(), 0u); layout_object->SetFirstInlineFragmentItemIndex(index); continue; } @@ -40,8 +52,51 @@ DCHECK_GT(last_index, 0u) << item; DCHECK_LT(last_index, items->size()); DCHECK_LT(last_index, index); + DCHECK_EQ((*items)[last_index]->DeltaToNextForSameLayoutObject(), 0u); (*items)[last_index]->SetDeltaToNextForSameLayoutObject(index - last_index); } } +void NGFragmentItems::ClearAssociatedFragments() const { + DCHECK(items_.IsEmpty() || items_[0]->IsContainer()); + if (items_.size() <= 1) + return; + LayoutObject* last_object = nullptr; + for (const auto& item : base::span<const std::unique_ptr<NGFragmentItem>>( + items_.begin() + 1, items_.end())) { + if (!ShouldAssociateWithLayoutObject(*item)) { + // These items are not associated and that no need to clear. + continue; + } + LayoutObject* object = item->GetMutableLayoutObject(); + if (!object || object == last_object) + continue; + if (object->IsInLayoutNGInlineFormattingContext()) + object->ClearFirstInlineFragmentItemIndex(); + last_object = object; + } +} + +// static +void NGFragmentItems::LayoutObjectWillBeMoved( + const LayoutObject& layout_object) { + NGInlineCursor cursor; + cursor.MoveTo(layout_object); + for (; cursor; cursor.MoveToNextForSameLayoutObject()) { + const NGFragmentItem* item = cursor.Current().Item(); + item->LayoutObjectWillBeMoved(); + } +} + +// static +void NGFragmentItems::LayoutObjectWillBeDestroyed( + const LayoutObject& layout_object) { + NGInlineCursor cursor; + cursor.MoveTo(layout_object); + for (; cursor; cursor.MoveToNextForSameLayoutObject()) { + const NGFragmentItem* item = cursor.Current().Item(); + item->LayoutObjectWillBeDestroyed(); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h index 76c95f1..44386167 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h
@@ -28,8 +28,13 @@ return UNLIKELY(first_line) ? first_line_text_content_ : text_content_; } - static void AssociateWithLayoutObject( - Vector<std::unique_ptr<NGFragmentItem>>* items); + // Associate/disassociate |NGFragmentItem|s with |LayoutObject|s. + void AssociateWithLayoutObject() const; + void ClearAssociatedFragments() const; + + // Notify when |LayoutObject| will be destroyed/moved. + static void LayoutObjectWillBeDestroyed(const LayoutObject& layout_object); + static void LayoutObjectWillBeMoved(const LayoutObject& layout_object); private: // TODO(kojii): inline capacity TBD.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc index 243c9d36..ec22f6f 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -217,7 +217,6 @@ const PhysicalSize& outer_size, void* data) { ConvertToPhysical(writing_mode, direction, outer_size); - NGFragmentItems::AssociateWithLayoutObject(&items_); new (data) NGFragmentItems(this); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc index bb39e1b4..15030129 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -902,6 +902,10 @@ DCHECK(&root); SetRoot(root); if (!HasRoot()) { + if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { + MakeNull(); + return; + } const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object); if (!fragments.IsInLayoutNGInlineFormattingContext() || @@ -915,9 +919,8 @@ if (fragment_items_) { const wtf_size_t item_index = layout_object.FirstInlineFragmentItemIndex(); if (!item_index) { - // TODO(yosin): Once we update all |LayoutObject::FirstInlineFragment()| - // clients, we should replace to |return MakeNull()| - MoveToItem(SlowFirstItemIteratorFor(layout_object)); + DCHECK(items_.end() == SlowFirstItemIteratorFor(layout_object)); + MakeNull(); return; } const unsigned span_index = SpanIndexFromItemIndex(item_index);
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc index 44f6ed8..af33302b 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h" #include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h" #include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h" +#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h" namespace blink { @@ -69,6 +70,21 @@ return InFlowChildCountIs(node, 2); } +bool IsValidMathMLUnderOver(const NGBlockNode& node) { + auto* scripted = + DynamicTo<MathMLUnderOverElement>(node.GetLayoutBox()->GetNode()); + switch (scripted->scriptType()) { + case MathMLUnderOverElement::ScriptType::kUnder: + case MathMLUnderOverElement::ScriptType::kOver: + return InFlowChildCountIs(node, 2); + case MathMLUnderOverElement::ScriptType::kUnderOver: + return InFlowChildCountIs(node, 3); + default: + NOTREACHED(); + return false; + } +} + namespace { inline LayoutUnit DefaultFractionLineThickness(const ComputedStyle& style) {
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h index 366e1a811..e08dc08 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
@@ -26,6 +26,7 @@ NGLayoutInputNode NextSiblingInFlow(const NGBlockNode&); bool IsValidMathMLFraction(const NGBlockNode&); +bool IsValidMathMLUnderOver(const NGBlockNode&); inline float RuleThicknessFallback(const ComputedStyle& style) { // This function returns a value for the default rule thickness (TeX's
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc new file mode 100644 index 0000000..f1b0a75 --- /dev/null +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
@@ -0,0 +1,290 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h" + +#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h" +#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h" +#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h" +#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h" +#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h" +#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" +#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h" + +namespace blink { +namespace { + +// Describes the amount to shift to apply to the under/over boxes. +// Data is populated from the OpenType MATH table. +// If the OpenType MATH table is not present fallback values are used. +// https://mathml-refresh.github.io/mathml-core/#base-with-underscript +// https://mathml-refresh.github.io/mathml-core/#base-with-overscript +struct UnderOverVerticalParameters { + bool use_under_over_bar_fallback; + LayoutUnit under_gap_min; + LayoutUnit over_gap_min; + LayoutUnit under_shift_min; + LayoutUnit over_shift_min; + LayoutUnit under_extra_descender; + LayoutUnit over_extra_ascender; + LayoutUnit accent_base_height; +}; + +UnderOverVerticalParameters GetUnderOverVerticalParameters( + const ComputedStyle& style) { + UnderOverVerticalParameters parameters; + + if (!OpenTypeMathSupport::HasMathData( + style.GetFont().PrimaryFont()->PlatformData().GetHarfBuzzFace())) { + // The MATH table specification does not really provide any suggestions, + // except for some underbar/overbar values and AccentBaseHeight. + LayoutUnit default_line_thickness = + LayoutUnit(RuleThicknessFallback(style)); + parameters.under_gap_min = 3 * default_line_thickness; + parameters.over_gap_min = 3 * default_line_thickness; + parameters.under_extra_descender = default_line_thickness; + parameters.over_extra_ascender = default_line_thickness; + parameters.accent_base_height = + LayoutUnit(style.GetFont().PrimaryFont()->GetFontMetrics().XHeight()); + parameters.use_under_over_bar_fallback = true; + return parameters; + } + + // The base is a large operator so we read UpperLimit/LowerLimit constants + // from the MATH table. + parameters.under_gap_min = LayoutUnit( + MathConstant(style, OpenTypeMathSupport::MathConstants::kLowerLimitGapMin) + .value_or(0)); + parameters.over_gap_min = LayoutUnit( + MathConstant(style, OpenTypeMathSupport::MathConstants::kUpperLimitGapMin) + .value_or(0)); + parameters.under_shift_min = LayoutUnit( + MathConstant( + style, OpenTypeMathSupport::MathConstants::kLowerLimitBaselineDropMin) + .value_or(0)); + parameters.over_shift_min = LayoutUnit( + MathConstant( + style, OpenTypeMathSupport::MathConstants::kUpperLimitBaselineRiseMin) + .value_or(0)); + parameters.use_under_over_bar_fallback = false; + return parameters; +} + +} // namespace + +NGMathUnderOverLayoutAlgorithm::NGMathUnderOverLayoutAlgorithm( + const NGLayoutAlgorithmParams& params) + : NGLayoutAlgorithm(params), + border_scrollbar_padding_(params.fragment_geometry.border + + params.fragment_geometry.padding + + params.fragment_geometry.scrollbar) { + DCHECK(params.space.IsNewFormattingContext()); + container_builder_.SetIsNewFormattingContext( + params.space.IsNewFormattingContext()); + container_builder_.SetInitialFragmentGeometry(params.fragment_geometry); +} + +void NGMathUnderOverLayoutAlgorithm::GatherChildren(NGBlockNode* base, + NGBlockNode* over, + NGBlockNode* under) { + auto script_type = + DynamicTo<MathMLUnderOverElement>(Node().GetLayoutBox()->GetNode()) + ->scriptType(); + for (NGLayoutInputNode child = Node().FirstChild(); child; + child = child.NextSibling()) { + NGBlockNode block_child = To<NGBlockNode>(child); + if (child.IsOutOfFlowPositioned()) { + container_builder_.AddOutOfFlowChildCandidate( + block_child, {border_scrollbar_padding_.inline_start, + border_scrollbar_padding_.block_start}); + continue; + } + if (!*base) { + *base = block_child; + continue; + } + switch (script_type) { + case MathMLUnderOverElement::ScriptType::kUnder: + DCHECK(!*under); + *under = block_child; + break; + case MathMLUnderOverElement::ScriptType::kOver: + DCHECK(!*over); + *over = block_child; + break; + case MathMLUnderOverElement::ScriptType::kUnderOver: + if (!*under) { + *under = block_child; + continue; + } + DCHECK(!*over); + *over = block_child; + break; + default: + NOTREACHED(); + } + } +} + +scoped_refptr<const NGLayoutResult> NGMathUnderOverLayoutAlgorithm::Layout() { + DCHECK(!BreakToken()); + DCHECK(IsValidMathMLUnderOver(Node())); + + NGBlockNode base = nullptr; + NGBlockNode over = nullptr; + NGBlockNode under = nullptr; + GatherChildren(&base, &over, &under); + + const LogicalSize border_box_size = container_builder_.InitialBorderBoxSize(); + auto child_available_size = + ShrinkAvailableSize(border_box_size, border_scrollbar_padding_); + + LayoutUnit block_offset = border_scrollbar_padding_.block_start; + UnderOverVerticalParameters parameters = + GetUnderOverVerticalParameters(Style()); + // TODO(rbuis): handle stretchy operators. + // TODO(rbuis): handle accent. + + // All children are positioned centered relative to the container (and + // therefore centered relative to themselves). + if (over) { + auto over_space = CreateConstraintSpaceForMathChild( + Node(), child_available_size, ConstraintSpace(), over); + scoped_refptr<const NGLayoutResult> over_layout_result = + over.Layout(over_space); + NGBoxStrut over_margins = + ComputeMarginsFor(over_space, over.Style(), ConstraintSpace()); + NGBoxFragment over_fragment( + ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(), + To<NGPhysicalBoxFragment>(over_layout_result->PhysicalFragment())); + block_offset += parameters.over_extra_ascender + over_margins.block_start; + LogicalOffset over_offset = { + border_scrollbar_padding_.inline_start + over_margins.inline_start + + (child_available_size.inline_size - + (over_fragment.InlineSize() + over_margins.InlineSum())) / + 2, + block_offset}; + container_builder_.AddChild(over_layout_result->PhysicalFragment(), + over_offset); + over.StoreMargins(ConstraintSpace(), over_margins); + if (parameters.use_under_over_bar_fallback) { + block_offset += over_fragment.BlockSize(); + block_offset += parameters.over_gap_min; + } else { + LayoutUnit over_ascent = + over_fragment.Baseline().value_or(over_fragment.BlockSize()); + block_offset += + std::max(over_fragment.BlockSize() + parameters.over_gap_min, + over_ascent + parameters.over_shift_min); + } + block_offset += over_margins.block_end; + } + + auto base_space = CreateConstraintSpaceForMathChild( + Node(), child_available_size, ConstraintSpace(), base); + auto base_layout_result = base.Layout(base_space); + auto base_margins = + ComputeMarginsFor(base_space, base.Style(), ConstraintSpace()); + + NGBoxFragment base_fragment( + ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(), + To<NGPhysicalBoxFragment>(base_layout_result->PhysicalFragment())); + + block_offset += base_margins.block_start; + LogicalOffset base_offset = { + border_scrollbar_padding_.inline_start + base_margins.inline_start + + (child_available_size.inline_size - + (base_fragment.InlineSize() + base_margins.InlineSum())) / + 2, + block_offset}; + container_builder_.AddChild(base_layout_result->PhysicalFragment(), + base_offset); + base.StoreMargins(ConstraintSpace(), base_margins); + block_offset += base_fragment.BlockSize() + base_margins.block_end; + + if (under) { + auto under_space = CreateConstraintSpaceForMathChild( + Node(), child_available_size, ConstraintSpace(), under); + scoped_refptr<const NGLayoutResult> under_layout_result = + under.Layout(under_space); + NGBoxStrut under_margins = + ComputeMarginsFor(under_space, under.Style(), ConstraintSpace()); + NGBoxFragment under_fragment( + ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction(), + To<NGPhysicalBoxFragment>(under_layout_result->PhysicalFragment())); + block_offset += under_margins.block_start; + if (parameters.use_under_over_bar_fallback) { + block_offset += parameters.under_gap_min; + } else { + LayoutUnit under_ascent = + under_fragment.Baseline().value_or(under_fragment.BlockSize()); + block_offset += std::max(parameters.under_gap_min, + parameters.under_shift_min - under_ascent); + } + LogicalOffset under_offset = { + border_scrollbar_padding_.inline_start + under_margins.inline_start + + (child_available_size.inline_size - + (under_fragment.InlineSize() + under_margins.InlineSum())) / + 2, + block_offset}; + block_offset += under_fragment.BlockSize(); + block_offset += parameters.under_extra_descender; + container_builder_.AddChild(under_layout_result->PhysicalFragment(), + under_offset); + under.StoreMargins(ConstraintSpace(), under_margins); + block_offset += under_margins.block_end; + } + + LayoutUnit base_ascent = + base_fragment.Baseline().value_or(base_fragment.BlockSize()); + container_builder_.SetBaseline(base_offset.block_offset + base_ascent); + + block_offset += border_scrollbar_padding_.block_end; + + LayoutUnit block_size = ComputeBlockSizeForFragment( + ConstraintSpace(), Style(), border_scrollbar_padding_, block_offset); + + container_builder_.SetIntrinsicBlockSize(block_offset); + container_builder_.SetBlockSize(block_size); + + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), container_builder_.Borders(), + &container_builder_) + .Run(); + + return container_builder_.ToBoxFragment(); +} + +base::Optional<MinMaxSizes> NGMathUnderOverLayoutAlgorithm::ComputeMinMaxSizes( + const MinMaxSizesInput& input) const { + DCHECK(IsValidMathMLUnderOver(Node())); + + base::Optional<MinMaxSizes> sizes = + CalculateMinMaxSizesIgnoringChildren(Node(), border_scrollbar_padding_); + if (sizes) + return sizes; + + sizes.emplace(); + LayoutUnit child_percentage_resolution_block_size = + CalculateChildPercentageBlockSizeForMinMax( + ConstraintSpace(), Node(), border_scrollbar_padding_, + input.percentage_resolution_block_size); + + MinMaxSizesInput child_input(child_percentage_resolution_block_size); + + for (NGLayoutInputNode child = Node().FirstChild(); child; + child = child.NextSibling()) { + if (child.IsOutOfFlowPositioned()) + continue; + auto child_sizes = + ComputeMinAndMaxContentContribution(Style(), child, child_input); + NGBoxStrut margins = ComputeMinMaxMargins(Style(), child); + child_sizes += margins.InlineSum(); + sizes->Encompass(child_sizes); + } + + *sizes += border_scrollbar_padding_.InlineSum(); + return sizes; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h new file mode 100644 index 0000000..57deb0f --- /dev/null +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h
@@ -0,0 +1,36 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_ + +#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h" +#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h" + +namespace blink { + +class CORE_EXPORT NGMathUnderOverLayoutAlgorithm + : public NGLayoutAlgorithm<NGBlockNode, + NGBoxFragmentBuilder, + NGBlockBreakToken> { + public: + explicit NGMathUnderOverLayoutAlgorithm( + const NGLayoutAlgorithmParams& params); + + scoped_refptr<const NGLayoutResult> Layout() override; + + base::Optional<MinMaxSizes> ComputeMinMaxSizes( + const MinMaxSizesInput&) const override; + + private: + void GatherChildren(NGBlockNode* base, + NGBlockNode* second, + NGBlockNode* third); + + const NGBoxStrut border_scrollbar_padding_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_UNDER_OVER_LAYOUT_ALGORITHM_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 868dbbc..11af02e 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -33,6 +33,7 @@ #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h" #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_space_layout_algorithm.h" +#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h" @@ -55,6 +56,7 @@ #include "third_party/blink/renderer/core/mathml/mathml_element.h" #include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h" #include "third_party/blink/renderer/core/mathml/mathml_space_element.h" +#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/text/writing_mode.h" @@ -64,6 +66,11 @@ namespace { +inline bool HasInlineChildren(LayoutBlockFlow* block_flow) { + auto* child = GetLayoutObjectForFirstChildNode(block_flow); + return child && AreNGBlockFlowChildrenInline(block_flow); +} + inline LayoutMultiColumnFlowThread* GetFlowThread( const LayoutBlockFlow* block_flow) { if (!block_flow) @@ -99,6 +106,9 @@ else if (IsA<MathMLFractionElement>(element) && IsValidMathMLFraction(params.node)) CreateAlgorithmAndRun<NGMathFractionLayoutAlgorithm>(params, callback); + else if (IsA<MathMLUnderOverElement>(element) && + IsValidMathMLUnderOver(params.node)) + CreateAlgorithmAndRun<NGMathUnderOverLayoutAlgorithm>(params, callback); else CreateAlgorithmAndRun<NGMathRowLayoutAlgorithm>(params, callback); } @@ -628,9 +638,8 @@ box_->SetCachedLayoutResult(layout_result); if (block_flow) { - auto* child = GetLayoutObjectForFirstChildNode(block_flow); - bool has_inline_children = - child && AreNGBlockFlowChildrenInline(block_flow); + const NGFragmentItems* items = physical_fragment.Items(); + bool has_inline_children = items || HasInlineChildren(block_flow); // Don't consider display-locked objects as having any children. if (has_inline_children && box_->LayoutBlockedByDisplayLock( @@ -656,15 +665,18 @@ physical_fragment, physical_fragment.Size().width, Style().IsFlippedBlocksWritingMode()); block_flow->SetPaintFragment(break_token, &physical_fragment); - } else { - CopyFragmentDataToLayoutBoxForInlineChildren(physical_fragment); + } else if (items) { + CopyFragmentItemsToLayoutBox(physical_fragment, *items); } } else { // We still need to clear paint fragments in case it had inline children, // and thus had NGPaintFragment. block_flow->ClearNGInlineNodeData(); - block_flow->SetPaintFragment(break_token, nullptr); + if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) + block_flow->SetPaintFragment(break_token, nullptr); } + } else { + DCHECK(!physical_fragment.HasItems()); } CopyFragmentDataToLayoutBox(constraint_space, *layout_result, break_token); @@ -1140,14 +1152,13 @@ } } -void NGBlockNode::CopyFragmentDataToLayoutBoxForInlineChildren( - const NGPhysicalBoxFragment& container) { +void NGBlockNode::CopyFragmentItemsToLayoutBox( + const NGPhysicalBoxFragment& container, + const NGFragmentItems& items) { DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); - const NGFragmentItems* items = container.Items(); - if (!items) - return; + bool initial_container_is_flipped = Style().IsFlippedBlocksWritingMode(); - for (NGInlineCursor cursor(*items); cursor; cursor.MoveToNext()) { + for (NGInlineCursor cursor(items); cursor; cursor.MoveToNext()) { if (const NGPhysicalBoxFragment* child = cursor.Current().BoxFragment()) { // Replaced elements and inline blocks need Location() set relative to // their block container.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h index 7ccb575..5e90d19 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -174,8 +174,8 @@ const NGConstraintSpace&, const NGLayoutResult&, const NGBlockBreakToken* previous_break_token); - void CopyFragmentDataToLayoutBoxForInlineChildren( - const NGPhysicalBoxFragment& container); + void CopyFragmentItemsToLayoutBox(const NGPhysicalBoxFragment& container, + const NGFragmentItems& items); void CopyFragmentDataToLayoutBoxForInlineChildren( const NGPhysicalContainerFragment& container, LayoutUnit initial_container_width,
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource.cc b/third_party/blink/renderer/core/loader/resource/font_resource.cc index 794161c5..0a601bd 100644 --- a/third_party/blink/renderer/core/loader/resource/font_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/font_resource.cc
@@ -119,6 +119,8 @@ if (!font_data_) SetStatus(ResourceStatus::kDecodeError); + else + ClearData(); } return font_data_; }
diff --git a/third_party/blink/renderer/core/mathml/BUILD.gn b/third_party/blink/renderer/core/mathml/BUILD.gn index 2204ea93..a78e6696 100644 --- a/third_party/blink/renderer/core/mathml/BUILD.gn +++ b/third_party/blink/renderer/core/mathml/BUILD.gn
@@ -14,5 +14,7 @@ "mathml_row_element.h", "mathml_space_element.cc", "mathml_space_element.h", + "mathml_under_over_element.cc", + "mathml_under_over_element.h", ] }
diff --git a/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 index 17fd2a645..2ecb7857 100644 --- a/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 +++ b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
@@ -76,6 +76,18 @@ interfaceName: "MathMLElement", }, { + name: "mover", + interfaceName: "MathMLUnderOverElement", + }, + { + name: "munder", + interfaceName: "MathMLUnderOverElement", + }, + { + name: "munderover", + interfaceName: "MathMLUnderOverElement", + }, + { name: "semantics", interfaceName: "MathMLRowElement", },
diff --git a/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc b/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc new file mode 100644 index 0000000..f0ce234 --- /dev/null +++ b/third_party/blink/renderer/core/mathml/mathml_under_over_element.cc
@@ -0,0 +1,35 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/mathml/mathml_under_over_element.h" + +#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" + +namespace blink { + +static MathMLUnderOverElement::ScriptType scriptTypeOf( + const QualifiedName& tagName) { + if (tagName == mathml_names::kMunderTag) + return MathMLUnderOverElement::ScriptType::kUnder; + if (tagName == mathml_names::kMoverTag) + return MathMLUnderOverElement::ScriptType::kOver; + DCHECK_EQ(tagName, mathml_names::kMunderoverTag); + return MathMLUnderOverElement::ScriptType::kUnderOver; +} + +MathMLUnderOverElement::MathMLUnderOverElement(const QualifiedName& tagName, + Document& document) + : MathMLElement(tagName, document), script_type_(scriptTypeOf(tagName)) {} + +LayoutObject* MathMLUnderOverElement::CreateLayoutObject( + const ComputedStyle& style, + LegacyLayout legacy) { + if (!RuntimeEnabledFeatures::MathMLCoreEnabled() || + !style.IsDisplayMathType() || legacy == LegacyLayout::kForce) + return MathMLElement::CreateLayoutObject(style, legacy); + return new LayoutNGMathMLBlock(this); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/mathml/mathml_under_over_element.h b/third_party/blink/renderer/core/mathml/mathml_under_over_element.h new file mode 100644 index 0000000..50f3b690 --- /dev/null +++ b/third_party/blink/renderer/core/mathml/mathml_under_over_element.h
@@ -0,0 +1,50 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_ + +#include "third_party/blink/renderer/core/mathml/mathml_element.h" + +namespace blink { + +class Document; + +class CORE_EXPORT MathMLUnderOverElement final : public MathMLElement { + public: + MathMLUnderOverElement(const QualifiedName& tagName, Document& document); + + enum class ScriptType { + kUnder, + kOver, + kUnderOver, + }; + ScriptType scriptType() const { return script_type_; } + + private: + const ScriptType script_type_; + LayoutObject* CreateLayoutObject(const ComputedStyle&, + LegacyLayout legacy) override; +}; + +template <> +inline bool IsElementOfType<const MathMLUnderOverElement>(const Node& node) { + return IsA<MathMLUnderOverElement>(node); +} +template <> +struct DowncastTraits<MathMLUnderOverElement> { + static bool AllowFrom(const Node& node) { + auto* mathml_element = DynamicTo<MathMLElement>(node); + return mathml_element && AllowFrom(*mathml_element); + } + static bool AllowFrom(const MathMLElement& mathml_element) { + return mathml_element.HasTagName(mathml_names::kMunderTag) || + mathml_element.HasTagName(mathml_names::kMoverTag) || + mathml_element.HasTagName(mathml_names::kMunderoverTag); + } +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_UNDER_OVER_ELEMENT_H_
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 1b430137..cf28300c 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -436,8 +436,17 @@ if (client) { client->ConvertViewportToWindow(&screen_rect); WebRect view_rect = client->ViewRect(); - screen_rect.x += view_rect.x; - screen_rect.y += view_rect.y; + + base::CheckedNumeric<int> screen_rect_x = screen_rect.x; + base::CheckedNumeric<int> screen_rect_y = screen_rect.y; + + screen_rect_x += view_rect.x; + screen_rect_y += view_rect.y; + + screen_rect.x = + screen_rect_x.ValueOrDefault(std::numeric_limits<int>::max()); + screen_rect.y = + screen_rect_y.ValueOrDefault(std::numeric_limits<int>::max()); } return screen_rect;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 1cca3d0..82722d99 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -3007,6 +3007,7 @@ // This will be used in the loop finding matching fragment from ancestor flow // threads after no matching from parent_fragments. LayoutUnit logical_top_in_containing_flow_thread; + bool crossed_flow_thread = false; if (object_.IsLayoutFlowThread()) { const auto& flow_thread = ToLayoutFlowThread(object_); @@ -3025,6 +3026,7 @@ return context; } } + crossed_flow_thread = true; } else { bool parent_is_under_same_flow_thread; auto* pagination_layer = @@ -3057,6 +3059,7 @@ } logical_top_in_containing_flow_thread = logical_top_in_flow_thread; + crossed_flow_thread = !parent_is_under_same_flow_thread; } // Found no matching parent fragment. Use parent_fragments[0] to inherit @@ -3081,14 +3084,35 @@ if (!container->FirstFragment().HasLocalBorderBoxProperties()) continue; - for (const auto* fragment = &container->FirstFragment(); fragment; - fragment = fragment->NextFragment()) { - if (fragment->LogicalTopInFlowThread() == - logical_top_in_containing_flow_thread) { - // Found a matching fragment in an ancestor container. Use the - // container's content clip as the clip state. - context.current.clip = &fragment->PostOverflowClip(); - return context; + const FragmentData* container_fragment = &container->FirstFragment(); + while (container_fragment->LogicalTopInFlowThread() < + logical_top_in_containing_flow_thread && + container_fragment->NextFragment()) + container_fragment = container_fragment->NextFragment(); + + if (container_fragment->LogicalTopInFlowThread() == + logical_top_in_containing_flow_thread) { + // Found a matching fragment in an ancestor container. Use the + // container's content clip as the clip state. + context.current.clip = &container_fragment->PostOverflowClip(); + return context; + } + + // We didn't find corresponding fragment in the container because the + // fragment fully overflows the container. If the container has overflow + // clip, then this fragment should be under |container_fragment|. + // This works only when the current fragment and the overflow clip are under + // the same flow thread. In other cases, we just leave it broken, which will + // be fixed by LayoutNG block fragments hopefully. + if (!crossed_flow_thread) { + if (const auto* container_properties = + container_fragment->PaintProperties()) { + if (const auto* overflow_clip = container_properties->OverflowClip()) { + context.logical_top_in_flow_thread = + container_fragment->LogicalTopInFlowThread(); + context.current.clip = overflow_clip; + return context; + } } } @@ -3097,6 +3121,7 @@ FragmentLogicalTopInParentFlowThread( ToLayoutFlowThread(*container), logical_top_in_containing_flow_thread); + crossed_flow_thread = true; } } @@ -3181,8 +3206,16 @@ } // Match to parent fragments from the same containing flow thread. - new_fragment_contexts.push_back( - ContextForFragment(fragment_clip, logical_top_in_flow_thread)); + auto fragment_context = + ContextForFragment(fragment_clip, logical_top_in_flow_thread); + // ContextForFragment may override logical_top_in_flow_thread. + logical_top_in_flow_thread = fragment_context.logical_top_in_flow_thread; + // Avoid fragment with duplicated overridden logical_top_in_flow_thread. + if (new_fragment_contexts.size() && + new_fragment_contexts.back().logical_top_in_flow_thread == + logical_top_in_flow_thread) + break; + new_fragment_contexts.push_back(fragment_context); if (current_fragment_data) { if (!current_fragment_data->NextFragment())
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index e2fcffa..289444c 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -4322,6 +4322,33 @@ EXPECT_EQ(1u, NumFragments(GetLayoutObjectByElementId("layer"))); } +TEST_P(PaintPropertyTreeBuilderTest, OverflowClipUnderMultiColumn) { + SetBodyInnerHTML(R"HTML( + <style>body { margin: 0; }</style> + <div style='columns: 4; height: 100px; column-fill: auto; column-gap: 0'> + <div id='clip' style='height: 200px; overflow: hidden'> + <div id='child1' style='height: 400px'></div> + <div id='child2' style='height: 400px'></div> + </div> + </div> + )HTML"); + + const auto* clip = GetLayoutObjectByElementId("clip"); + ASSERT_EQ(2u, NumFragments(clip)); + EXPECT_EQ(LayoutUnit(), FragmentAt(clip, 0).LogicalTopInFlowThread()); + EXPECT_EQ(LayoutUnit(100), FragmentAt(clip, 1).LogicalTopInFlowThread()); + const auto* child1 = GetLayoutObjectByElementId("child1"); + ASSERT_EQ(2u, NumFragments(child1)); + EXPECT_EQ(LayoutUnit(), FragmentAt(child1, 0).LogicalTopInFlowThread()); + EXPECT_EQ(PhysicalOffset(), FragmentAt(child1, 0).PaintOffset()); + EXPECT_EQ(LayoutUnit(100), FragmentAt(child1, 1).LogicalTopInFlowThread()); + EXPECT_EQ(PhysicalOffset(200, -100), FragmentAt(child1, 1).PaintOffset()); + const auto* child2 = GetLayoutObjectByElementId("child2"); + ASSERT_EQ(1u, NumFragments(child2)); + EXPECT_EQ(LayoutUnit(100), FragmentAt(child2, 0).LogicalTopInFlowThread()); + EXPECT_EQ(PhysicalOffset(200, 300), FragmentAt(child2, 0).PaintOffset()); +} + TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) { SetBodyInnerHTML(R"HTML( <style>body { margin: 0; }</style>
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 10d3535..cd061dd 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1072,7 +1072,7 @@ } void ComputedStyle::AddCallbackSelector(const String& selector) { - if (!CallbackSelectorsInternal().Contains(selector)) + if (!CallbackSelectors().Contains(selector)) MutableCallbackSelectorsInternal().push_back(selector); }
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 3896c54d0..790c5be 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -94,6 +94,7 @@ namespace css_longhand { +class Appearance; class BackgroundColor; class BorderBottomColor; class BorderLeftColor; @@ -125,7 +126,6 @@ class StopColor; class Stroke; class TextDecorationColor; -class WebkitAppearance; class WebkitTapHighlightColor; class WebkitTextEmphasisColor; class WebkitTextFillColor; @@ -238,7 +238,7 @@ friend class LayoutTheme; friend class StyleAdjuster; friend class StyleCascade; - friend class css_longhand::WebkitAppearance; + friend class css_longhand::Appearance; // Editing has to only reveal unvisited info. friend class ApplyStyleCommand; // Editing has to only reveal unvisited info. @@ -707,7 +707,7 @@ OutlineColorIsCurrentColor() == other.OutlineColorIsCurrentColor() && OutlineColor() == other.OutlineColor() && OutlineStyle() == other.OutlineStyle() && - OutlineOffsetInternal() == other.OutlineOffsetInternal() && + OutlineOffset() == other.OutlineOffset() && OutlineStyleIsAuto() == other.OutlineStyleIsAuto(); } @@ -727,11 +727,6 @@ } void SetOutlineWidth(uint16_t v) { SetOutlineWidthInternal(LayoutUnit(v)); } - // outline-offset - int OutlineOffset() const { - return OutlineOffsetInternal(); - } - // -webkit-perspective-origin-x const Length& PerspectiveOriginX() const { return PerspectiveOrigin().X(); } void SetPerspectiveOriginX(const Length& v) { @@ -1261,9 +1256,6 @@ CSSTransitionData& AccessTransitions(); // Callback selectors. - const Vector<String>& CallbackSelectors() const { - return CallbackSelectorsInternal(); - } void AddCallbackSelector(const String& selector); // Non-property flags.
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 index cd6337f..1189ff2 100644 --- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 +++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -81,7 +81,7 @@ { name: "DiffNeedsFullLayoutAndPaintInvalidation", fields_to_diff: ["padding-top", "padding-left", "padding-right", - "padding-bottom", "-webkit-appearance", "-webkit-line-clamp", + "padding-bottom", "appearance", "-webkit-line-clamp", "text-overflow", "shape-margin", "order", "-webkit-highlight", "text-indent", "text-align-last", "TextIndentLine", "-internal-effective-zoom", "word-break", "overflow-wrap", "-webkit-line-break",
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index 9327fd0..16db031 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -638,7 +638,7 @@ default_value: "Vector<String>()", include_paths: ["third_party/blink/renderer/platform/wtf/vector.h", "third_party/blink/renderer/platform/wtf/text/wtf_string.h"], - computed_style_custom_functions: ["getter", "setter"], + computed_style_custom_functions: ["setter"], }, { name: "PaintImages",
diff --git a/third_party/blink/renderer/core/svg/svg_length.cc b/third_party/blink/renderer/core/svg/svg_length.cc index 9a0108d1..ffcafb4 100644 --- a/third_party/blink/renderer/core/svg/svg_length.cc +++ b/third_party/blink/renderer/core/svg/svg_length.cc
@@ -165,10 +165,7 @@ case kCalcLength: case kCalcNumber: case kCalcPercent: - case kCalcPercentNumber: case kCalcPercentLength: - case kCalcLengthNumber: - case kCalcPercentLengthNumber: return true; default: return false;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 3d46994..52204d7 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3727,6 +3727,7 @@ case ax::mojom::Role::kVideo: case ax::mojom::Role::kWebArea: case ax::mojom::Role::kWebView: + case ax::mojom::Role::kWindow: result = false; break; @@ -3822,7 +3823,6 @@ } case ax::mojom::Role::kUnknown: - case ax::mojom::Role::kMaxValue: LOG(ERROR) << "ax::mojom::Role::kUnknown for " << GetNode(); NOTREACHED(); break;
diff --git a/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.cc b/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.cc index 097ab0c0..b3b4376 100644 --- a/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.cc +++ b/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.cc
@@ -19,7 +19,9 @@ PeriodicSyncManager::PeriodicSyncManager( ServiceWorkerRegistration* registration, scoped_refptr<base::SequencedTaskRunner> task_runner) - : registration_(registration), task_runner_(std::move(task_runner)) { + : registration_(registration), + task_runner_(std::move(task_runner)), + background_sync_service_(registration_->GetExecutionContext()) { DCHECK(registration_); } @@ -89,13 +91,13 @@ return promise; } -const mojo::Remote<mojom::blink::PeriodicBackgroundSyncService>& +mojom::blink::PeriodicBackgroundSyncService* PeriodicSyncManager::GetBackgroundSyncServiceRemote() { if (!background_sync_service_.is_bound()) { Platform::Current()->GetBrowserInterfaceBroker()->GetInterface( - background_sync_service_.BindNewPipeAndPassReceiver()); + background_sync_service_.BindNewPipeAndPassReceiver(task_runner_)); } - return background_sync_service_; + return background_sync_service_.get(); } void PeriodicSyncManager::RegisterCallback( @@ -186,6 +188,7 @@ void PeriodicSyncManager::Trace(Visitor* visitor) { visitor->Trace(registration_); + visitor->Trace(background_sync_service_); ScriptWrappable::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.h b/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.h index b76e055..0b7111a3 100644 --- a/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.h +++ b/third_party/blink/renderer/modules/background_sync/periodic_sync_manager.h
@@ -7,9 +7,10 @@ #include "base/memory/scoped_refptr.h" #include "base/sequenced_task_runner.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/background_sync/background_sync.mojom-blink.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -43,8 +44,7 @@ // mojo::Remote<mojom::blink::PeriodicBackgroundSyncService>. A connection // with the the browser's BackgroundSyncService is created the first time this // method is called. - const mojo::Remote<mojom::blink::PeriodicBackgroundSyncService>& - GetBackgroundSyncServiceRemote(); + mojom::blink::PeriodicBackgroundSyncService* GetBackgroundSyncServiceRemote(); // Callbacks void RegisterCallback(ScriptPromiseResolver* resolver, @@ -59,7 +59,8 @@ Member<ServiceWorkerRegistration> registration_; scoped_refptr<base::SequencedTaskRunner> task_runner_; - mojo::Remote<mojom::blink::PeriodicBackgroundSyncService> + HeapMojoRemote<mojom::blink::PeriodicBackgroundSyncService, + HeapMojoWrapperMode::kWithoutContextObserver> background_sync_service_; };
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc index 76483de..29cd652 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_storage.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -104,7 +104,7 @@ // The context may be destroyed and the mojo connection unbound. However the // object may live on, reject any requests after the context is destroyed. - if (!cache_storage_remote_) { + if (!cache_storage_remote_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError)); return promise; @@ -177,7 +177,7 @@ // The context may be destroyed and the mojo connection unbound. However the // object may live on, reject any requests after the context is destroyed. - if (!cache_storage_remote_) { + if (!cache_storage_remote_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError)); return promise; @@ -237,7 +237,7 @@ // The context may be destroyed and the mojo connection unbound. However the // object may live on, reject any requests after the context is destroyed. - if (!cache_storage_remote_) { + if (!cache_storage_remote_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError)); return promise; @@ -297,7 +297,7 @@ // The context may be destroyed and the mojo connection unbound. However the // object may live on, reject any requests after the context is destroyed. - if (!cache_storage_remote_) { + if (!cache_storage_remote_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError)); return promise; @@ -374,7 +374,7 @@ // The context may be destroyed and the mojo connection unbound. However the // object may live on, reject any requests after the context is destroyed. - if (!cache_storage_remote_) { + if (!cache_storage_remote_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError)); return promise; @@ -457,9 +457,10 @@ CacheStorage::CacheStorage(ExecutionContext* context, GlobalFetch::ScopedFetcher* fetcher) - : ExecutionContextLifecycleObserver(context), + : ExecutionContextClient(context), scoped_fetcher_(fetcher), blob_client_list_(MakeGarbageCollected<CacheStorageBlobClientList>()), + cache_storage_remote_(context), ever_used_(false) { // See https://bit.ly/2S0zRAS for task types. scoped_refptr<base::SingleThreadTaskRunner> task_runner = @@ -471,8 +472,9 @@ mojo::PendingRemote<mojom::blink::CacheStorage> info = service_worker->TakeCacheStorage(); if (info) { - cache_storage_remote_ = mojo::Remote<mojom::blink::CacheStorage>( - std::move(info), task_runner); + cache_storage_remote_ = + HeapMojoRemote<mojom::blink::CacheStorage>(context); + cache_storage_remote_.Bind(std::move(info), task_runner); return; } } @@ -497,8 +499,9 @@ void CacheStorage::Trace(Visitor* visitor) { visitor->Trace(scoped_fetcher_); visitor->Trace(blob_client_list_); + visitor->Trace(cache_storage_remote_); ScriptWrappable::Trace(visitor); - ExecutionContextLifecycleObserver::Trace(visitor); + ExecutionContextClient::Trace(visitor); } bool CacheStorage::IsAllowed(ScriptState* script_state) { @@ -509,8 +512,4 @@ return allowed_.value(); } -void CacheStorage::ContextDestroyed() { - cache_storage_remote_.reset(); -} - } // namespace blink
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage.h b/third_party/blink/renderer/modules/cache_storage/cache_storage.h index 87a4563e..00fb1777 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_storage.h +++ b/third_party/blink/renderer/modules/cache_storage/cache_storage.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/macros.h" #include "base/optional.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -17,6 +16,7 @@ #include "third_party/blink/renderer/modules/cache_storage/cache.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -27,7 +27,7 @@ class CacheStorage final : public ScriptWrappable, public ActiveScriptWrappable<CacheStorage>, - public ExecutionContextLifecycleObserver { + public ExecutionContextClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(CacheStorage); @@ -46,7 +46,6 @@ bool HasPendingActivity() const override; void Trace(Visitor*) override; - void ContextDestroyed() override; private: ScriptPromise MatchImpl(ScriptState*, @@ -58,7 +57,7 @@ Member<GlobalFetch::ScopedFetcher> scoped_fetcher_; Member<CacheStorageBlobClientList> blob_client_list_; - mojo::Remote<mojom::blink::CacheStorage> cache_storage_remote_; + HeapMojoRemote<mojom::blink::CacheStorage> cache_storage_remote_; base::Optional<bool> allowed_; bool ever_used_;
diff --git a/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc b/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc index 6d2c8842..e6982582 100644 --- a/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc +++ b/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -31,7 +32,7 @@ } // namespace KeyboardLayout::KeyboardLayout(ExecutionContext* context) - : ExecutionContextClient(context) {} + : ExecutionContextClient(context), service_(context) {} ScriptPromise KeyboardLayout::GetKeyboardLayoutMap( ScriptState* script_state, @@ -75,14 +76,15 @@ } bool KeyboardLayout::EnsureServiceConnected() { - if (!service_) { + if (!service_.is_bound()) { LocalFrame* frame = GetFrame(); if (!frame) { return false; } frame->GetBrowserInterfaceBroker().GetInterface( - service_.BindNewPipeAndPassReceiver()); - DCHECK(service_); + service_.BindNewPipeAndPassReceiver( + frame->GetTaskRunner(TaskType::kMiscPlatformAPI))); + DCHECK(service_.is_bound()); } return true; } @@ -116,6 +118,7 @@ void KeyboardLayout::Trace(Visitor* visitor) { visitor->Trace(script_promise_resolver_); + visitor->Trace(service_); ExecutionContextClient::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/keyboard/keyboard_layout.h b/third_party/blink/renderer/modules/keyboard/keyboard_layout.h index 4307f83..526fc43 100644 --- a/third_party/blink/renderer/modules/keyboard/keyboard_layout.h +++ b/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
@@ -6,12 +6,13 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_LAYOUT_H_ #include "base/macros.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace blink { @@ -45,7 +46,9 @@ Member<ScriptPromiseResolver> script_promise_resolver_; - mojo::Remote<mojom::blink::KeyboardLockService> service_; + HeapMojoRemote<mojom::blink::KeyboardLockService, + HeapMojoWrapperMode::kWithoutContextObserver> + service_; DISALLOW_COPY_AND_ASSIGN(KeyboardLayout); };
diff --git a/third_party/blink/renderer/modules/push_messaging/push_provider.cc b/third_party/blink/renderer/modules/push_messaging/push_provider.cc index 082166d..06d82392 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_provider.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_provider.cc
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/modules/push_messaging/push_messaging_utils.h" #include "third_party/blink/renderer/modules/push_messaging/push_subscription.h" #include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/functional.h" @@ -22,7 +23,8 @@ const char PushProvider::kSupplementName[] = "PushProvider"; PushProvider::PushProvider(ServiceWorkerRegistration& registration) - : Supplement<ServiceWorkerRegistration>(registration) {} + : Supplement<ServiceWorkerRegistration>(registration), + push_messaging_manager_(nullptr) {} // static PushProvider* PushProvider::From(ServiceWorkerRegistration* registration) { @@ -41,9 +43,11 @@ // static mojom::blink::PushMessaging* PushProvider::GetPushMessagingRemote() { - if (!push_messaging_manager_) { + if (!push_messaging_manager_.is_bound()) { Platform::Current()->GetBrowserInterfaceBroker()->GetInterface( - push_messaging_manager_.BindNewPipeAndPassReceiver()); + push_messaging_manager_.BindNewPipeAndPassReceiver( + GetSupplementable()->GetExecutionContext()->GetTaskRunner( + TaskType::kMiscPlatformAPI))); } return push_messaging_manager_.get(); @@ -122,6 +126,11 @@ WTF::Passed(std::move(callbacks)))); } +void PushProvider::Trace(Visitor* visitor) { + visitor->Trace(push_messaging_manager_); + Supplement::Trace(visitor); +} + void PushProvider::DidGetSubscription( std::unique_ptr<PushSubscriptionCallbacks> callbacks, mojom::blink::PushGetRegistrationStatus status,
diff --git a/third_party/blink/renderer/modules/push_messaging/push_provider.h b/third_party/blink/renderer/modules/push_messaging/push_provider.h index 4ac49e8..7f528d19 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_provider.h +++ b/third_party/blink/renderer/modules/push_messaging/push_provider.h
@@ -11,11 +11,12 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/single_thread_task_runner.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-blink-forward.h" #include "third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/supplementable.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -46,6 +47,8 @@ void Unsubscribe(std::unique_ptr<PushUnsubscribeCallbacks> callbacks); void GetSubscription(std::unique_ptr<PushSubscriptionCallbacks> callbacks); + void Trace(Visitor*) override; + private: // Returns an initialized PushMessaging service. A connection will be // established after the first call to this method. @@ -64,7 +67,9 @@ mojom::blink::PushGetRegistrationStatus status, mojom::blink::PushSubscriptionPtr subscription); - mojo::Remote<mojom::blink::PushMessaging> push_messaging_manager_; + HeapMojoRemote<mojom::blink::PushMessaging, + HeapMojoWrapperMode::kWithoutContextObserver> + push_messaging_manager_; DISALLOW_COPY_AND_ASSIGN(PushProvider); };
diff --git a/third_party/blink/renderer/modules/serial/serial.cc b/third_party/blink/renderer/modules/serial/serial.cc index 4051e1d1..00ab0eb 100644 --- a/third_party/blink/renderer/modules/serial/serial.cc +++ b/third_party/blink/renderer/modules/serial/serial.cc
@@ -42,7 +42,9 @@ } // namespace Serial::Serial(ExecutionContext& execution_context) - : ExecutionContextLifecycleObserver(&execution_context) {} + : ExecutionContextLifecycleObserver(&execution_context), + service_(&execution_context), + receiver_(this, &execution_context) {} ExecutionContext* Serial::GetExecutionContext() const { return ExecutionContextLifecycleObserver::GetExecutionContext(); @@ -155,10 +157,6 @@ return resolver->Promise(); } -void Serial::Dispose() { - receiver_.reset(); -} - void Serial::GetPort( const base::UnguessableToken& token, mojo::PendingReceiver<device::mojom::blink::SerialPort> receiver) { @@ -167,6 +165,8 @@ } void Serial::Trace(Visitor* visitor) { + visitor->Trace(service_); + visitor->Trace(receiver_); visitor->Trace(get_ports_promises_); visitor->Trace(request_port_promises_); visitor->Trace(port_cache_); @@ -196,7 +196,7 @@ void Serial::EnsureServiceConnection() { DCHECK(GetExecutionContext()); - if (service_) + if (service_.is_bound()) return; auto task_runner = @@ -206,7 +206,7 @@ service_.set_disconnect_handler( WTF::Bind(&Serial::OnServiceConnectionError, WrapWeakPersistent(this))); - service_->SetClient(receiver_.BindNewPipeAndPassRemote()); + service_->SetClient(receiver_.BindNewPipeAndPassRemote(task_runner)); } void Serial::OnServiceConnectionError() {
diff --git a/third_party/blink/renderer/modules/serial/serial.h b/third_party/blink/renderer/modules/serial/serial.h index bd3115f..52a4664 100644 --- a/third_party/blink/renderer/modules/serial/serial.h +++ b/third_party/blink/renderer/modules/serial/serial.h
@@ -5,8 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_H_ -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/serial/serial.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" @@ -14,6 +12,9 @@ #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { @@ -29,7 +30,6 @@ public mojom::blink::SerialServiceClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(Serial); - USING_PRE_FINALIZER(Serial, Dispose); public: explicit Serial(ExecutionContext&); @@ -53,7 +53,6 @@ const SerialPortRequestOptions*, ExceptionState&); - void Dispose(); void GetPort( const base::UnguessableToken& token, mojo::PendingReceiver<device::mojom::blink::SerialPort> receiver); @@ -72,8 +71,12 @@ Vector<mojom::blink::SerialPortInfoPtr>); void OnRequestPort(ScriptPromiseResolver*, mojom::blink::SerialPortInfoPtr); - mojo::Remote<mojom::blink::SerialService> service_; - mojo::Receiver<mojom::blink::SerialServiceClient> receiver_{this}; + HeapMojoRemote<mojom::blink::SerialService, + HeapMojoWrapperMode::kWithoutContextObserver> + service_; + HeapMojoReceiver<mojom::blink::SerialServiceClient, + HeapMojoWrapperMode::kWithoutContextObserver> + receiver_; HeapHashSet<Member<ScriptPromiseResolver>> get_ports_promises_; HeapHashSet<Member<ScriptPromiseResolver>> request_port_promises_; HeapHashMap<String, WeakMember<SerialPort>> port_cache_;
diff --git a/third_party/blink/renderer/modules/serial/serial_port.cc b/third_party/blink/renderer/modules/serial/serial_port.cc index 574011b..fd971dbe 100644 --- a/third_party/blink/renderer/modules/serial/serial_port.cc +++ b/third_party/blink/renderer/modules/serial/serial_port.cc
@@ -159,7 +159,10 @@ } // namespace SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info) - : info_(std::move(info)), parent_(parent) {} + : info_(std::move(info)), + parent_(parent), + port_(GetExecutionContext()), + client_receiver_(this, GetExecutionContext()) {} SerialPort::~SerialPort() = default; @@ -173,7 +176,7 @@ return ScriptPromise(); } - if (port_) { + if (port_.is_bound()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "The port is already open."); return ScriptPromise(); @@ -262,7 +265,10 @@ } mojo::PendingRemote<device::mojom::blink::SerialPortClient> client; - parent_->GetPort(info_->token, port_.BindNewPipeAndPassReceiver()); + parent_->GetPort( + info_->token, + port_.BindNewPipeAndPassReceiver( + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI))); port_.set_disconnect_handler( WTF::Bind(&SerialPort::OnConnectionError, WrapWeakPersistent(this))); @@ -282,7 +288,7 @@ if (readable_) return readable_; - if (!port_ || open_resolver_ || closing_ || read_fatal_) + if (!port_.is_bound() || open_resolver_ || closing_ || read_fatal_) return nullptr; mojo::ScopedDataPipeConsumerHandle readable_pipe; @@ -303,7 +309,7 @@ if (writable_) return writable_; - if (!port_ || open_resolver_ || closing_ || write_fatal_) + if (!port_.is_bound() || open_resolver_ || closing_ || write_fatal_) return nullptr; mojo::ScopedDataPipeProducerHandle writable_pipe; @@ -321,7 +327,7 @@ ScriptPromise SerialPort::getSignals(ScriptState* script_state, ExceptionState& exception_state) { - if (!port_) { + if (!port_.is_bound()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, kPortClosed); return ScriptPromise(); @@ -338,7 +344,7 @@ ScriptPromise SerialPort::setSignals(ScriptState* script_state, const SerialOutputSignals* signals, ExceptionState& exception_state) { - if (!port_) { + if (!port_.is_bound()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, kPortClosed); return ScriptPromise(); @@ -369,7 +375,7 @@ ScriptPromise SerialPort::close(ScriptState* script_state, ExceptionState& exception_state) { - if (!port_) { + if (!port_.is_bound()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "The port is already closed."); return ScriptPromise(); @@ -415,7 +421,7 @@ DCHECK(!writable_); DCHECK(!close_resolver_); - if (!port_) + if (!port_.is_bound()) return ScriptPromise::CastUndefined(script_state); close_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state); @@ -445,6 +451,8 @@ void SerialPort::Trace(Visitor* visitor) { visitor->Trace(parent_); + visitor->Trace(port_); + visitor->Trace(client_receiver_); visitor->Trace(readable_); visitor->Trace(underlying_source_); visitor->Trace(writable_); @@ -455,12 +463,6 @@ ScriptWrappable::Trace(visitor); } -void SerialPort::Dispose() { - // The binding holds a raw pointer to this object which must be released when - // it becomes garbage. - client_receiver_.reset(); -} - ExecutionContext* SerialPort::GetExecutionContext() const { return parent_->GetExecutionContext(); } @@ -564,7 +566,9 @@ ScriptState::Scope scope(script_state); InitializeReadableStream(script_state, std::move(readable_pipe)); InitializeWritableStream(script_state, std::move(writable_pipe)); - client_receiver_.Bind(std::move(client_receiver)); + client_receiver_.Bind( + std::move(client_receiver), + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)); open_resolver_->Resolve(); open_resolver_ = nullptr; }
diff --git a/third_party/blink/renderer/modules/serial/serial_port.h b/third_party/blink/renderer/modules/serial/serial_port.h index 06f923b..a7701f75 100644 --- a/third_party/blink/renderer/modules/serial/serial_port.h +++ b/third_party/blink/renderer/modules/serial/serial_port.h
@@ -6,8 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_PORT_H_ #include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/serial.mojom-blink-forward.h" #include "third_party/blink/public/mojom/serial/serial.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" @@ -15,6 +13,9 @@ #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace base { class UnguessableToken; @@ -37,7 +38,6 @@ public device::mojom::blink::SerialPortClient { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(SerialPort); - USING_PRE_FINALIZER(SerialPort, Dispose); public: explicit SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info); @@ -64,7 +64,6 @@ void ContextDestroyed(); void Trace(Visitor*) override; - void Dispose(); // ActiveScriptWrappable ExecutionContext* GetExecutionContext() const; @@ -95,8 +94,10 @@ const Member<Serial> parent_; uint32_t buffer_size_ = 0; - mojo::Remote<device::mojom::blink::SerialPort> port_; - mojo::Receiver<device::mojom::blink::SerialPortClient> client_receiver_{this}; + HeapMojoRemote<device::mojom::blink::SerialPort> port_; + HeapMojoReceiver<device::mojom::blink::SerialPortClient, + HeapMojoWrapperMode::kWithoutContextObserver> + client_receiver_; Member<ReadableStream> readable_; Member<SerialPortUnderlyingSource> underlying_source_;
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc index e7dfc4a..db9cdb7 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
@@ -29,6 +29,7 @@ WakeLock::WakeLock(Document& document) : ExecutionContextLifecycleObserver(&document), PageVisibilityObserver(document.GetPage()), + permission_service_(document.ToExecutionContext()), managers_{ MakeGarbageCollected<WakeLockManager>(document.ToExecutionContext(), WakeLockType::kScreen), @@ -42,6 +43,7 @@ WakeLock::WakeLock(DedicatedWorkerGlobalScope& worker_scope) : ExecutionContextLifecycleObserver(&worker_scope), PageVisibilityObserver(nullptr), + permission_service_(&worker_scope), managers_{MakeGarbageCollected<WakeLockManager>(&worker_scope, WakeLockType::kScreen), MakeGarbageCollected<WakeLockManager>(&worker_scope, @@ -271,10 +273,11 @@ } PermissionService* WakeLock::GetPermissionService() { - if (!permission_service_) { + if (!permission_service_.is_bound()) { ConnectToPermissionService( GetExecutionContext(), - permission_service_.BindNewPipeAndPassReceiver()); + permission_service_.BindNewPipeAndPassReceiver( + GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI))); } return permission_service_.get(); } @@ -282,6 +285,7 @@ void WakeLock::Trace(Visitor* visitor) { for (const WakeLockManager* manager : managers_) visitor->Trace(manager); + visitor->Trace(permission_service_); PageVisibilityObserver::Trace(visitor); ExecutionContextLifecycleObserver::Trace(visitor); ScriptWrappable::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.h b/third_party/blink/renderer/modules/wake_lock/wake_lock.h index a2379f07..27b1daf 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock.h +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.h
@@ -17,6 +17,8 @@ #include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace WTF { @@ -68,7 +70,9 @@ base::OnceCallback<void(mojom::blink::PermissionStatus)> callback); mojom::blink::PermissionService* GetPermissionService(); - mojo::Remote<mojom::blink::PermissionService> permission_service_; + HeapMojoRemote<mojom::blink::PermissionService, + HeapMojoWrapperMode::kWithoutContextObserver> + permission_service_; // https://w3c.github.io/wake-lock/#concepts-and-state-record // Each platform wake lock (one per wake lock type) has an associated state
diff --git a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc index 39120ec..d0ceda2 100644 --- a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc +++ b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
@@ -30,16 +30,16 @@ MIDIAccessInitializer::MIDIAccessInitializer(ScriptState* script_state, const MIDIOptions* options) - : ScriptPromiseResolver(script_state), options_(options) {} + : ScriptPromiseResolver(script_state), + options_(options), + permission_service_(GetExecutionContext()) {} void MIDIAccessInitializer::Dispose() { dispatcher_.reset(); - permission_service_.reset(); } void MIDIAccessInitializer::ContextDestroyed() { dispatcher_.reset(); - permission_service_.reset(); ScriptPromiseResolver::ContextDestroyed(); } @@ -126,6 +126,7 @@ void MIDIAccessInitializer::Trace(Visitor* visitor) { visitor->Trace(options_); + visitor->Trace(permission_service_); ScriptPromiseResolver::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h index 8ae5e42..e5489990 100644 --- a/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h +++ b/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h
@@ -7,7 +7,6 @@ #include <memory> #include "media/midi/midi_service.mojom-blink-forward.h" -#include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -16,6 +15,7 @@ #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/webmidi/midi_dispatcher.h" #include "third_party/blink/renderer/modules/webmidi/midi_port.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -101,7 +101,7 @@ Vector<PortDescriptor> port_descriptors_; Member<const MIDIOptions> options_; - mojo::Remote<mojom::blink::PermissionService> permission_service_; + HeapMojoRemote<mojom::blink::PermissionService> permission_service_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 898e130..ba5f4c63 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -508,6 +508,10 @@ status: "test", }, { + name: "CSSRevert", + depends_on: ["CSSCascade"], + }, + { name: "CSSSnapSize", status: "experimental", },
diff --git a/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc b/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc index bcfb0be1..784fccc 100644 --- a/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc +++ b/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
@@ -11,17 +11,26 @@ namespace WTF { +template <typename T> +int* const ValueInstanceCount<T>::kDeletedValue = + reinterpret_cast<int*>(static_cast<uintptr_t>(-1)); + TEST(NewLinkedHashSetTest, CopyConstructAndAssignInt) { - NewLinkedHashSet<int> set1; + using Set = NewLinkedHashSet<ValueInstanceCount<int>>; + // Declare the counters before the set, because they have to outlive teh set. + int counter1 = 0; + int counter2 = 0; + int counter3 = 0; + Set set1; EXPECT_EQ(set1.size(), 0u); EXPECT_TRUE(set1.IsEmpty()); - set1.insert(1); - set1.insert(2); - set1.insert(3); + set1.insert(ValueInstanceCount<int>(&counter1, 1)); + set1.insert(ValueInstanceCount<int>(&counter2, 2)); + set1.insert(ValueInstanceCount<int>(&counter3, 3)); EXPECT_EQ(set1.size(), 3u); - NewLinkedHashSet<int> set2(set1); + Set set2(set1); EXPECT_EQ(set2.size(), 3u); - NewLinkedHashSet<int> set3; + Set set3; EXPECT_EQ(set3.size(), 0u); set3 = set2; EXPECT_EQ(set3.size(), 3u); @@ -29,17 +38,24 @@ auto it2 = set2.begin(); auto it3 = set3.begin(); for (int i = 0; i < 3; i++) { - EXPECT_EQ(*it1, i + 1); - EXPECT_EQ(*it2, i + 1); - EXPECT_EQ(*it3, i + 1); + EXPECT_EQ(it1->Value(), i + 1); + EXPECT_EQ(it2->Value(), i + 1); + EXPECT_EQ(it3->Value(), i + 1); ++it1; ++it2; ++it3; } + + // Each object is now in all 3 sets. + // Count 2x because each set uses hash map and vector. + EXPECT_EQ(counter1, 6); + EXPECT_EQ(counter2, 6); + EXPECT_EQ(counter3, 6); } TEST(NewLinkedHashSetTest, CopyConstructAndAssignIntPtr) { - NewLinkedHashSet<int*> set1; + using Set = NewLinkedHashSet<int*>; + Set set1; EXPECT_EQ(set1.size(), 0u); EXPECT_TRUE(set1.IsEmpty()); std::unique_ptr<int> int1 = std::make_unique<int>(1); @@ -49,9 +65,9 @@ set1.insert(int2.get()); set1.insert(int3.get()); EXPECT_EQ(set1.size(), 3u); - NewLinkedHashSet<int*> set2(set1); + Set set2(set1); EXPECT_EQ(set2.size(), 3u); - NewLinkedHashSet<int*> set3; + Set set3; EXPECT_EQ(set3.size(), 0u); set3 = set2; EXPECT_EQ(set3.size(), 3u); @@ -67,6 +83,7 @@ ++it3; } + // Changing the pointed values in one set should change it in all sets. for (int* ptr : set1) *ptr += 1000; it1 = set1.begin(); @@ -83,16 +100,17 @@ } TEST(NewLinkedHashSetTest, CopyConstructAndAssignString) { - NewLinkedHashSet<String> set1; + using Set = NewLinkedHashSet<String>; + Set set1; EXPECT_EQ(set1.size(), 0u); EXPECT_TRUE(set1.IsEmpty()); set1.insert("1"); set1.insert("2"); set1.insert("3"); EXPECT_EQ(set1.size(), 3u); - NewLinkedHashSet<String> set2(set1); + Set set2(set1); EXPECT_EQ(set2.size(), 3u); - NewLinkedHashSet<String> set3; + Set set3; EXPECT_EQ(set3.size(), 0u); set3 = set2; EXPECT_EQ(set3.size(), 3u); @@ -107,22 +125,40 @@ ++it2; ++it3; } + + // Changing one set should not affect the others. + set1.clear(); + set1.insert("11"); + set1.insert("12"); + set1.insert("13"); + it1 = set1.begin(); + it2 = set2.begin(); + it3 = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(*it1, String(Vector<UChar>({'1', '1' + i}))); + EXPECT_EQ(*it2, String(Vector<UChar>({'1' + i}))); + EXPECT_EQ(*it3, String(Vector<UChar>({'1' + i}))); + ++it1; + ++it2; + ++it3; + } } TEST(NewLinkedHashSetTest, MoveConstructAndAssignInt) { - NewLinkedHashSet<ValueInstanceCount<int>> set1; - EXPECT_EQ(set1.size(), 0u); - EXPECT_TRUE(set1.IsEmpty()); + using Set = NewLinkedHashSet<ValueInstanceCount<int>>; int counter1 = 0; int counter2 = 0; int counter3 = 0; + Set set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); set1.insert(ValueInstanceCount<int>(&counter1, 1)); set1.insert(ValueInstanceCount<int>(&counter2, 2)); set1.insert(ValueInstanceCount<int>(&counter3, 3)); EXPECT_EQ(set1.size(), 3u); - NewLinkedHashSet<ValueInstanceCount<int>> set2(std::move(set1)); + Set set2(std::move(set1)); EXPECT_EQ(set2.size(), 3u); - NewLinkedHashSet<ValueInstanceCount<int>> set3; + Set set3; EXPECT_EQ(set3.size(), 0u); set3 = std::move(set2); EXPECT_EQ(set3.size(), 3u); @@ -138,7 +174,7 @@ EXPECT_EQ(counter2, 2); EXPECT_EQ(counter3, 2); - NewLinkedHashSet<ValueInstanceCount<int>> set4(set3); + Set set4(set3); // Copy constructor was used, each object is in set3 and set4. EXPECT_EQ(counter1, 4); EXPECT_EQ(counter2, 4); @@ -146,19 +182,20 @@ } TEST(NewLinkedHashSetTest, MoveConstructAndAssignString) { - NewLinkedHashSet<ValueInstanceCount<String>> set1; - EXPECT_EQ(set1.size(), 0u); - EXPECT_TRUE(set1.IsEmpty()); + using Set = NewLinkedHashSet<ValueInstanceCount<String>>; int counter1 = 0; int counter2 = 0; int counter3 = 0; + Set set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); set1.insert(ValueInstanceCount<String>(&counter1, "1")); set1.insert(ValueInstanceCount<String>(&counter2, "2")); set1.insert(ValueInstanceCount<String>(&counter3, "3")); EXPECT_EQ(set1.size(), 3u); - NewLinkedHashSet<ValueInstanceCount<String>> set2(std::move(set1)); + Set set2(std::move(set1)); EXPECT_EQ(set2.size(), 3u); - NewLinkedHashSet<ValueInstanceCount<String>> set3; + Set set3; EXPECT_EQ(set3.size(), 0u); set3 = std::move(set2); EXPECT_EQ(set3.size(), 3u); @@ -174,7 +211,7 @@ EXPECT_EQ(counter2, 2); EXPECT_EQ(counter3, 2); - NewLinkedHashSet<ValueInstanceCount<String>> set4(set3); + Set set4(set3); // Copy constructor was used, each object is in set3 and set4. EXPECT_EQ(counter1, 4); EXPECT_EQ(counter2, 4); @@ -372,7 +409,9 @@ Set::const_iterator it = set.begin(); ++it; + EXPECT_TRUE(set.Contains(2)); set.erase(it); + EXPECT_FALSE(set.Contains(2)); it = set.begin(); EXPECT_EQ(*it, 1); ++it; @@ -382,7 +421,9 @@ ++it; EXPECT_EQ(*it, 5); + EXPECT_TRUE(set.Contains(3)); set.erase(3); + EXPECT_FALSE(set.Contains(3)); it = set.begin(); EXPECT_EQ(*it, 1); ++it;
diff --git a/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h b/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h index 60383b8a..ef44f8f6 100644 --- a/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h +++ b/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
@@ -79,16 +79,6 @@ VectorTraits<ValueType>::kCanCopyWithMemcpy; static const bool kCanMoveWithMemcpy = VectorTraits<ValueType>::kCanMoveWithMemcpy; - - // Needs to be shadowing because |VectorTraitsBase::IsDeletedValue| uses call - // by value, which means we need to define copy constructor of - // |VectorBackedLinkedList|. We can remove this function if we change - // |VectorTraitsBase::IsDeletedValue| to use call by reference. - static bool IsDeletedValue( - const VectorBackedLinkedListNode<ValueType, Allocator>& node) { - NOTREACHED(); - return false; - } }; // VectorBackedLinkedList maintains a linked list through its contents such that
diff --git a/third_party/blink/renderer/platform/wtf/vector_traits.h b/third_party/blink/renderer/platform/wtf/vector_traits.h index 0efa4ccf..25c0c7b7 100644 --- a/third_party/blink/renderer/platform/wtf/vector_traits.h +++ b/third_party/blink/renderer/platform/wtf/vector_traits.h
@@ -66,7 +66,7 @@ // Vectors do not support deleting values. static constexpr bool kCanHaveDeletedValue = false; - static bool IsDeletedValue(T value) { return false; } + static bool IsDeletedValue(const T& value) { return false; } }; template <typename T>
diff --git a/third_party/blink/renderer/platform/wtf/wtf_test_helper.h b/third_party/blink/renderer/platform/wtf/wtf_test_helper.h index 35b1e73..3e09b94 100644 --- a/third_party/blink/renderer/platform/wtf/wtf_test_helper.h +++ b/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
@@ -182,26 +182,30 @@ template <typename T> class ValueInstanceCount final { public: + static int* const kDeletedValue; + ValueInstanceCount() : counter_(nullptr), value_(T()) {} explicit ValueInstanceCount(int* counter, T value = T()) : counter_(counter), value_(value) { - DCHECK(counter_); - *counter = 1; + if (counter_ && counter_ != kDeletedValue) + ++*counter_; } ValueInstanceCount(const ValueInstanceCount& other) : counter_(other.counter_), value_(other.value_) { - if (counter_) + if (counter_ && counter_ != kDeletedValue) ++*counter_; } ValueInstanceCount& operator=(const ValueInstanceCount& other) { + if (counter_ && counter_ != kDeletedValue) + --*counter_; counter_ = other.counter_; value_ = other.value_; - if (counter_) + if (counter_ && counter_ != kDeletedValue) ++*counter_; return *this; } ~ValueInstanceCount() { - if (counter_) + if (counter_ && counter_ != kDeletedValue) --*counter_; } @@ -221,9 +225,11 @@ static bool IsEmptyValue(const ValueInstanceCount<T>& value) { return !value.Counter(); } - static void ConstructDeletedValue(ValueInstanceCount<T>& slot, bool) {} + static void ConstructDeletedValue(ValueInstanceCount<T>& slot, bool) { + slot = ValueInstanceCount<T>(ValueInstanceCount<T>::kDeletedValue); + } static bool IsDeletedValue(const ValueInstanceCount<T>& value) { - return false; + return value.Counter() == ValueInstanceCount<T>::kDeletedValue; } };
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 6ff43aa..a6932c6 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -177,6 +177,8 @@ virtual/composite-after-paint/scrollingcoordinator/* [ Pass ] # --- End CompositeAfterPaint Tests -- +crbug.com/1067174 wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html [ Failure ] + # Subpixel differences crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ] @@ -311,10 +313,6 @@ crbug.com/918155 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested-2.html [ Failure ] crbug.com/918155 virtual/prefer_compositing_to_lcd_text/scrollbars/overlay-scrollbar-over-child-layer-nested.html [ Failure ] -crbug.com/981719 external/wpt/css/css-ui/appearance-textfield-001.html [ Failure ] -crbug.com/981719 [ Linux ] external/wpt/css/css-ui/webkit-appearance-textfield-001.html [ Failure ] -crbug.com/981719 [ Win ] external/wpt/css/css-ui/webkit-appearance-textfield-001.html [ Failure ] - # WebGPU tests are only run on GPU bots, so they are skipped by default and run # separately from other Web Tests. external/wpt/webgpu/* [ Skip ] @@ -1038,6 +1036,7 @@ crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-nested-margin-004.xht [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-nested-margin-005.xht [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-overflow-000.xht [ Failure ] +crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-overflow-clip.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-overflowing-001.xht [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-reduce-000.xht [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-rule-000.xht [ Failure ] @@ -1631,6 +1630,7 @@ crbug.com/6606 external/wpt/mathml/presentation-markup/operators/mo-form-dynamic.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/operators/mo-form-minus-plus.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/operators/mo-form.html [ Failure ] +crbug.com/6606 external/wpt/mathml/presentation-markup/operators/mo-movablelimits.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/operators/mo-paint-lspace-rspace.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/operators/operator-dictionary-001.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/operators/operator-dictionary-002.html [ Failure ] @@ -1641,8 +1641,6 @@ crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/subsup-5.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/subsup-parameters-1.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/subsup-parameters-2.html [ Failure ] -crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/underover-1.html [ Failure ] -crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/underover-parameters-1.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/underover-parameters-2.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/underover-parameters-3.html [ Failure ] crbug.com/6606 external/wpt/mathml/presentation-markup/scripts/underover-parameters-4.html [ Failure ] @@ -1681,9 +1679,6 @@ crbug.com/6606 external/wpt/mathml/relations/css-styling/mathvariant-script.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/mathvariant-stretched.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/mathvariant-tailed.html [ Failure ] -crbug.com/6606 external/wpt/mathml/relations/css-styling/padding-border-margin/border-002.html [ Failure ] -crbug.com/6606 external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002.html [ Failure ] -crbug.com/6606 external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/visibility-003.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/width-height-001.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/html5-tree/href-click-1.html [ Failure ] @@ -3122,9 +3117,6 @@ # FontFace object failures detected by WPT test crbug.com/965409 external/wpt/css/css-font-loading/fontface-descriptor-updates.html [ Failure ] -# Various menulist appearance failures in WPT -crbug.com/968164 external/wpt/css/css-ui/appearance-menulist-button-002.html [ Failure ] - # Implement text-decoration-thickness and text-decoration-offset crbug.com/785230 external/wpt/css/css-text-decor/text-underline-offset-002.html [ Failure ] crbug.com/785230 external/wpt/css/css-text-decor/text-decoration-thickness-001.html [ Failure ] @@ -3166,6 +3158,7 @@ crbug.com/947951 [ Win ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html [ Pass Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.10 ] external/wpt/fetch/origin/assorted.window.html [ Failure Timeout ] crbug.com/626703 [ Linux ] external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ] crbug.com/626703 [ Mac ] external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ] @@ -3432,7 +3425,6 @@ crbug.com/626703 external/wpt/webrtc/RTCRtpTransceiver.https.html [ Crash Timeout ] crbug.com/626703 external/wpt/css/css-writing-modes/text-combine-upright-all-001-manual.html [ Skip ] crbug.com/626703 external/wpt/css/css-writing-modes/text-combine-upright-digits-002-manual.html [ Skip ] -crbug.com/626703 external/wpt/css/css-ui/webkit-appearance-button-bevel-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/text-combine-upright-all-002-manual.html [ Skip ] crbug.com/626703 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/json-module/parse-error.tentative.html [ Timeout ] crbug.com/967018 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/css-module/* [ Failure ]
diff --git a/third_party/blink/web_tests/animations/svg-attribute-interpolation/svg-calc-interpolation.html b/third_party/blink/web_tests/animations/svg-attribute-interpolation/svg-calc-interpolation.html index 2db968d..448aa01 100644 --- a/third_party/blink/web_tests/animations/svg-attribute-interpolation/svg-calc-interpolation.html +++ b/third_party/blink/web_tests/animations/svg-attribute-interpolation/svg-calc-interpolation.html
@@ -40,13 +40,13 @@ from: '0%', to: '100' }, [ - {at: -0.25, is: 'calc(0% + -25)'}, + {at: -0.25, is: 'calc(0% + -25px)'}, {at: 0, is: '0%'}, - {at: 0.25, is: 'calc(0% + 25)'}, - {at: 0.5, is: 'calc(0% + 50)'}, - {at: 0.75, is: 'calc(0% + 75)'}, + {at: 0.25, is: 'calc(0% + 25px)'}, + {at: 0.5, is: 'calc(0% + 50px)'}, + {at: 0.75, is: 'calc(0% + 75px)'}, {at: 1, is: '100px'}, - {at: 1.25, is: 'calc(0% + 125)'} + {at: 1.25, is: 'calc(0% + 125px)'} ]); assertAttributeInterpolation({ property: 'cy',
diff --git a/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords-expected.txt b/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords-expected.txt new file mode 100644 index 0000000..9a569ede --- /dev/null +++ b/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords-expected.txt
@@ -0,0 +1,13 @@ +CONSOLE WARNING: line 32: The keyword 'inner-spin-button' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'media-slider' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'media-sliderthumb' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'media-volume-slider' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'media-volume-sliderthumb' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'slider-vertical' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'sliderthumb-horizontal' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'sliderthumb-vertical' specified to an 'appearance' property is not standardized. It will be removed in the future. +CONSOLE WARNING: line 32: The keyword 'searchfield-cancel-button' specified to an 'appearance' property is not standardized. It will be removed in the future. +This is a testharness.js-based test. +FAIL There should be consle warnings about non-standard appearance keywords assert_true: This should FAIL to have -expected.txt expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords.html b/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords.html new file mode 100644 index 0000000..4a74b34 --- /dev/null +++ b/third_party/blink/web_tests/css-parser/appearance-with-nonstandard-keywords.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<style> +/* See https://drafts.csswg.org/css-ui-4/#appearance-switching */ +.t { + appearance: auto; + appearance: checkbox; + appearance: radio; + appearance: push-button; + appearance: square-button; + appearance: button; + appearance: inner-spin-button; /* should be warned */ + appearance: listbox; + appearance: media-slider; /* should be warned */ + appearance: media-sliderthumb; /* should be warned */ + appearance: media-volume-slider; /* should be warned */ + appearance: media-volume-sliderthumb; /* should be warned */ + appearance: menulist; + appearance: menulist-button; + appearance: meter; + appearance: progress-bar; + appearance: slider-horizontal; + appearance: slider-vertical; /* should be warned */ + appearance: sliderthumb-horizontal; /* should be warned */ + appearance: sliderthumb-vertical; /* should be warned */ + appearance: searchfield; + appearance: searchfield-cancel-button; /* should be warned */ + appearance: textfield; + appearance: textarea; +} +</style> +<script> +test(() => { + assert_true(false, 'This should FAIL to have -expected.txt'); +}, 'There should be consle warnings about non-standard appearance keywords'); +</script>
diff --git a/third_party/blink/web_tests/css3/flexbox/stretch-input-in-column.html b/third_party/blink/web_tests/css3/flexbox/stretch-input-in-column.html deleted file mode 100644 index ffa0632..0000000 --- a/third_party/blink/web_tests/css3/flexbox/stretch-input-in-column.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html> -<link rel="stylesheet" href="resources/flexbox.css"> -<style> -.flexbox { - background-color: grey; -} -</style> -<body> -<p>Form controls that are stretched in a column flexbox should not overflow the flexbox.</p> -<div class="flexbox column"> - <input> -</div> -<div class="flexbox column align-content-flex-start"> - <textarea class="align-self-stretch"></textarea> -</div> -<div class="flexbox column wrap"> - <input type="button"> -</div> -<div class="flexbox column"> - <select></select> -</div> -<div class="flexbox column"> - <legend style="border: 2px solid black">legend</legend> -</div> -<div class="flexbox column wrap"> - <div type="border: 4px solid black; padding: 10px;"> -</div> -</body> -</html>
diff --git a/third_party/blink/web_tests/css3/flexbox/undefined-min-width.html b/third_party/blink/web_tests/css3/flexbox/undefined-min-width.html deleted file mode 100644 index ea3a5ee8..0000000 --- a/third_party/blink/web_tests/css3/flexbox/undefined-min-width.html +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE html> -<html> -<link href="resources/flexbox.css" rel="stylesheet"> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/check-layout-th.js"></script> -<body onload="checkLayout('.flexbox')"> -<div id=log></div> - -Test to make sure that we do not assert on this code. - -<div class="flexbox column" style="max-height: 0; overflow: hidden; line-height: 13px;" data-expected-height="0"> - <div style="min-height: 100%;" data-expected-height="0">This is a flex item.</div> - <div style="flex: none;" data-expected-height="13">Inflexible</div> -</div>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index 5261d35f..76204545 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -49773,6 +49773,18 @@ {} ] ], + "css/css-flexbox/stretch-input-in-column.html": [ + [ + "css/css-flexbox/stretch-input-in-column.html", + [ + [ + "/css/css-flexbox/reference/stretch-input-in-column-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-flexbox/stretch-obeys-min-max-001.html": [ [ "css/css-flexbox/stretch-obeys-min-max-001.html", @@ -57123,6 +57135,62 @@ } ] ], + "css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html": [ + [ + "css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html", + [ + [ + "/css/css-images/image-orientation/reference/svg-image-orientation-aspect-ratio-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 10, + 10 + ], + [ + 100, + 100 + ] + ] + ] + ] + } + ] + ], + "css/css-images/image-orientation/svg-image-orientation.html": [ + [ + "css/css-images/image-orientation/svg-image-orientation.html", + [ + [ + "/css/css-images/image-orientation/reference/svg-image-orientation-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 10, + 10 + ], + [ + 100, + 100 + ] + ] + ] + ] + } + ] + ], "css/css-images/image-set/image-set-rendering.html": [ [ "css/css-images/image-set/image-set-rendering.html", @@ -63183,6 +63251,18 @@ {} ] ], + "css/css-multicol/multicol-overflow-clip.html": [ + [ + "css/css-multicol/multicol-overflow-clip.html", + [ + [ + "/css/css-multicol/multicol-overflow-clip-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-multicol/multicol-overflowing-001.xht": [ [ "css/css-multicol/multicol-overflowing-001.xht", @@ -94255,18 +94335,6 @@ {} ] ], - "css/css-ui/appearance-button-bevel-001.html": [ - [ - "css/css-ui/appearance-button-bevel-001.html", - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "css/css-ui/appearance-checkbox-001.html": [ [ "css/css-ui/appearance-checkbox-001.html", @@ -95431,18 +95499,6 @@ {} ] ], - "css/css-ui/webkit-appearance-button-bevel-001.html": [ - [ - "css/css-ui/webkit-appearance-button-bevel-001.html", - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "css/css-ui/webkit-appearance-checkbox-001.html": [ [ "css/css-ui/webkit-appearance-checkbox-001.html", @@ -142791,6 +142847,9 @@ "css/css-flexbox/reference/position-fixed-001-ref.html": [ [] ], + "css/css-flexbox/reference/stretch-input-in-column-ref.html": [ + [] + ], "css/css-flexbox/reference/stretching-orthogonal-flows-ref.html": [ [] ], @@ -148863,6 +148922,12 @@ "css/css-images/image-orientation/reference/image-orientation-none-ref.html": [ [] ], + "css/css-images/image-orientation/reference/svg-image-orientation-aspect-ratio-ref.html": [ + [] + ], + "css/css-images/image-orientation/reference/svg-image-orientation-ref.html": [ + [] + ], "css/css-images/image-orientation/support/exif-orientation-1-ul-pre-rotated.jpg": [ [] ], @@ -149937,6 +150002,9 @@ "css/css-multicol/multicol-overflow-clip-positioned-ref.html": [ [] ], + "css/css-multicol/multicol-overflow-clip-ref.html": [ + [] + ], "css/css-multicol/multicol-overflowing-001-ref.xht": [ [] ], @@ -155919,18 +155987,6 @@ "css/css-ui/appearance-cssom-001-expected.txt": [ [] ], - "css/css-ui/appearance-initial-value-001-expected.txt": [ - [] - ], - "css/css-ui/appearance-parsing-expected.txt": [ - [] - ], - "css/css-ui/appearance-property-expected.txt": [ - [] - ], - "css/css-ui/appearance-serialization-expected.txt": [ - [] - ], "css/css-ui/appearance-textfield-001-ref.html": [ [] ], @@ -156783,15 +156839,6 @@ "css/css-ui/tools/appearance-build-webkit-reftests.py": [ [] ], - "css/css-ui/webkit-appearance-parsing-expected.txt": [ - [] - ], - "css/css-ui/webkit-appearance-property-expected.txt": [ - [] - ], - "css/css-ui/webkit-appearance-serialization-expected.txt": [ - [] - ], "css/css-values/META.yml": [ [] ], @@ -166941,9 +166988,6 @@ "html/cross-origin-opener-policy/coep-navigate-popup.https.html.headers": [ [] ], - "html/cross-origin-opener-policy/coep-redirect.https-expected.txt": [ - [] - ], "html/cross-origin-opener-policy/coep-redirect.https.html.headers": [ [] ], @@ -174093,9 +174137,6 @@ "infrastructure/testdriver/file_upload_data.txt": [ [] ], - "infrastructure/testdriver/send_keys-expected.txt": [ - [] - ], "infrastructure/webdriver/tests/conftest.py": [ [] ], @@ -176385,6 +176426,12 @@ "offscreen-canvas/text/2d.text.draw.stroke.basic.png": [ [] ], + "offscreen-canvas/text/2d.text.measure.width.space-expected.txt": [ + [] + ], + "offscreen-canvas/text/2d.text.measure.width.space.worker-expected.txt": [ + [] + ], "offscreen-canvas/the-offscreen-canvas/2d.getcontext.extraargs-expected.txt": [ [] ], @@ -187194,12 +187241,6 @@ "webauthn/OWNERS": [ [] ], - "webauthn/createcredential-passing.https-expected.txt": [ - [] - ], - "webauthn/getcredential-extensions.https-expected.txt": [ - [] - ], "webauthn/helpers.js": [ [] ], @@ -187776,6 +187817,12 @@ "webrtc-identity/idlharness.https.window-expected.txt": [ [] ], + "webrtc-insertable-streams/resources/blank.html": [ + [] + ], + "webrtc-insertable-streams/resources/serviceworker-failure.js": [ + [] + ], "webrtc-quic/META.yml": [ [] ], @@ -187995,6 +188042,12 @@ "webrtc/resources/RTCCertificate-postMessage-iframe.html": [ [] ], + "webrtc/simulcast/.eslintignore": [ + [] + ], + "webrtc/simulcast/simulcast.js": [ + [] + ], "webrtc/third_party/README.md": [ [] ], @@ -219363,6 +219416,12 @@ {} ] ], + "css/css-flexbox/flex-minimum-size-002.html": [ + [ + "css/css-flexbox/flex-minimum-size-002.html", + {} + ] + ], "css/css-flexbox/flex-minimum-width-flex-items-014.html": [ [ "css/css-flexbox/flex-minimum-width-flex-items-014.html", @@ -219387,6 +219446,12 @@ {} ] ], + "css/css-flexbox/flexbox-lines-must-be-stretched-by-default.html": [ + [ + "css/css-flexbox/flexbox-lines-must-be-stretched-by-default.html", + {} + ] + ], "css/css-flexbox/flexbox_first-letter.html": [ [ "css/css-flexbox/flexbox_first-letter.html", @@ -220155,6 +220220,18 @@ {} ] ], + "css/css-flexbox/percentage-heights-012.html": [ + [ + "css/css-flexbox/percentage-heights-012.html", + {} + ] + ], + "css/css-flexbox/percentage-margins-001.html": [ + [ + "css/css-flexbox/percentage-margins-001.html", + {} + ] + ], "css/css-flexbox/percentage-padding-001.html": [ [ "css/css-flexbox/percentage-padding-001.html", @@ -220191,6 +220268,18 @@ {} ] ], + "css/css-flexbox/radiobutton-min-size.html": [ + [ + "css/css-flexbox/radiobutton-min-size.html", + {} + ] + ], + "css/css-flexbox/relayout-align-items.html": [ + [ + "css/css-flexbox/relayout-align-items.html", + {} + ] + ], "css/css-flexbox/shrinking-column-flexbox.html": [ [ "css/css-flexbox/shrinking-column-flexbox.html", @@ -324024,6 +324113,18 @@ } ] ], + "webrtc-insertable-streams/RTCEncodedAudioFrame-serviceworker-failure.https.html": [ + [ + "webrtc-insertable-streams/RTCEncodedAudioFrame-serviceworker-failure.https.html", + {} + ] + ], + "webrtc-insertable-streams/RTCEncodedVideoFrame-serviceworker-failure.https.html": [ + [ + "webrtc-insertable-streams/RTCEncodedVideoFrame-serviceworker-failure.https.html", + {} + ] + ], "webrtc-quic/RTCQuicStream.https.html": [ [ "webrtc-quic/RTCQuicStream.https.html", @@ -324717,8 +324818,13 @@ [ "script", "./RTCPeerConnection-helper.js" + ], + [ + "timeout", + "long" ] - ] + ], + "timeout": "long" } ] ], @@ -324856,6 +324962,12 @@ {} ] ], + "webrtc/simulcast/basic.https.html": [ + [ + "webrtc/simulcast/basic.https.html", + {} + ] + ], "websockets/Close-1000-reason.any.js": [ [ "websockets/Close-1000-reason.any.html", @@ -382640,7 +382752,7 @@ "testharness" ], "css/css-flexbox/change-column-flex-width.html": [ - "bea59bc2444758c778bad914d3c18c4f2eb1cf7c", + "8dc370ac9d3e0da7837d10250a868c177c78af38", "testharness" ], "css/css-flexbox/column-flex-child-with-overflow-scroll.html": [ @@ -383239,6 +383351,10 @@ "c2eea80ca5b79818f6b7a9a36ab1ff64826b5218", "testharness" ], + "css/css-flexbox/flex-minimum-size-002.html": [ + "41a8cd705d0c3bbd970f923b0b1dbfdbcff2de57", + "testharness" + ], "css/css-flexbox/flex-minimum-width-flex-items-001.xht": [ "cd18483ba414160c46e30bc282dec0c2fcd2f418", "reftest" @@ -383427,6 +383543,10 @@ "850f1a42d4e48b1cb8e5a10bee24dfa3966ad7df", "reftest" ], + "css/css-flexbox/flexbox-lines-must-be-stretched-by-default.html": [ + "f705a3882b456244e6b916898ab1342a3cce5207", + "testharness" + ], "css/css-flexbox/flexbox-order-from-lowest.html": [ "34bc0276019d03c0dcf4121f412b3eb4a50260d1", "visual" @@ -384844,7 +384964,7 @@ "reftest" ], "css/css-flexbox/flexbox_width-change-and-relayout-children.html": [ - "a5f086d181454d67c5123cc0f9ff0525d21fa72c", + "06342679b62777213483442128b6429290f091d1", "testharness" ], "css/css-flexbox/flexbox_width-overflow.html": [ @@ -385887,6 +386007,14 @@ "fda9c9b4f306adbfc8cd0eeb06f700ad2a5e60a9", "testharness" ], + "css/css-flexbox/percentage-heights-012.html": [ + "63f63aa8ec91b441ebae0754153260cc7b8d6d37", + "testharness" + ], + "css/css-flexbox/percentage-margins-001.html": [ + "b98bfa1af875b6961b4819fa0e7f82a24fcf783d", + "testharness" + ], "css/css-flexbox/percentage-max-height-001.html": [ "8e6dd227a038c8f237c769dad8e92976fe9ca832", "reftest" @@ -385939,6 +386067,10 @@ "966f39f173952f01268dcd26a9a5892bf4a689a9", "testharness" ], + "css/css-flexbox/radiobutton-min-size.html": [ + "5703861bf7333b765c3edce6627db5f64e741626", + "testharness" + ], "css/css-flexbox/reference/Flexible-order-ref.html": [ "12e94ba598e74cd253f0f91daf7e88f44884b7fc", "support" @@ -386123,6 +386255,10 @@ "4943f537f747e6bf10c4e6c91ad8ae1fb58b72c6", "support" ], + "css/css-flexbox/reference/stretch-input-in-column-ref.html": [ + "85d2a49e3ec6576dd3d0599c13e56ec453000606", + "support" + ], "css/css-flexbox/reference/stretching-orthogonal-flows-ref.html": [ "3a3efaad5dd9abc98f1da0c37ddb33f6aba45594", "support" @@ -386171,6 +386307,10 @@ "369de990ff2190ea0e4592d4dfc354a8a8fcae16", "support" ], + "css/css-flexbox/relayout-align-items.html": [ + "0569d5143981259400bac7f5998e56338e617ef1", + "testharness" + ], "css/css-flexbox/scrollbars-auto-ref.html": [ "590b533d8d25ac45dbeb1e7eab7cd02f3c1e8b5b", "support" @@ -386211,6 +386351,10 @@ "918ac3818553b3e9a276da5b98114719b1a400c1", "testharness" ], + "css/css-flexbox/stretch-input-in-column.html": [ + "4136c45d17a6bf946a4f788d95458c04ac6c6a6d", + "reftest" + ], "css/css-flexbox/stretch-obeys-min-max-001.html": [ "4b7eb5a1f76a39fdad6956953270ab9bdf8a14c1", "reftest" @@ -398771,6 +398915,14 @@ "c4d140f1533b0aa31a7bcee6884f9b5f0fd206f5", "support" ], + "css/css-images/image-orientation/reference/svg-image-orientation-aspect-ratio-ref.html": [ + "728bfb202f22da7d155536d8d0e2fb88869cc384", + "support" + ], + "css/css-images/image-orientation/reference/svg-image-orientation-ref.html": [ + "345d6698fcf376051a0ffe33cd6c5496b4b362c8", + "support" + ], "css/css-images/image-orientation/support/exif-orientation-1-ul-pre-rotated.jpg": [ "33abbd152a775cfed8802fd3084167328533ac87", "support" @@ -398843,6 +398995,14 @@ "7d41aead39e38d1377ec9b1732ca53b0fbb1906c", "support" ], + "css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html": [ + "ee053442d0d65ad48e0ee03cd7f08a4da5b8555e", + "reftest" + ], + "css/css-images/image-orientation/svg-image-orientation.html": [ + "3b8255f2d41407e634ac127adb5c6d2809231b7c", + "reftest" + ], "css/css-images/image-set/image-set-parsing-expected.txt": [ "47b6b85f06cb0c1ff02c97788e0afce7c13407d7", "support" @@ -403003,6 +403163,14 @@ "184bfc7f18dadbade32192b777c6b21f345882af", "reftest" ], + "css/css-multicol/multicol-overflow-clip-ref.html": [ + "c061a1d6114572c307d058f545e4828e4910250a", + "support" + ], + "css/css-multicol/multicol-overflow-clip.html": [ + "af59ff92d4f740ee71c6e3e1378704dd6a1ebe86", + "reftest" + ], "css/css-multicol/multicol-overflowing-001-ref.xht": [ "d3a6c6e03c58c17f0dfa4f2e6d9b945e352216af", "support" @@ -411860,15 +412028,15 @@ "testharness" ], "css/css-text-decor/parsing/text-underline-position-computed.html": [ - "9019a58fa4830ae5541b3882bf42f385504d0bd4", + "a1bf54b068bc848a9e253500f692eeff692f4e61", "testharness" ], "css/css-text-decor/parsing/text-underline-position-invalid.html": [ - "5feea8ed531de3de31b0692603ae48c065056819", + "d3d0fe8838b15c25e341cb4622c34e6cf85ffb84", "testharness" ], "css/css-text-decor/parsing/text-underline-position-valid.html": [ - "fa05448f09e40f34de18ac6896d81269c1103dfa", + "ee238f075e5474604e89dcc55cf40cf4361a822e", "testharness" ], "css/css-text-decor/reference/line-through-vertical-ref.html": [ @@ -425216,7 +425384,7 @@ "testharness" ], "css/css-transitions/KeyframeEffect-setKeyframes.tentative-expected.txt": [ - "bef7b146dd95e4ee968c1fb7e54ef9afd847cb59", + "f45b2f68dac9f201a01d779515d4bf6ec66f07c4", "support" ], "css/css-transitions/KeyframeEffect-setKeyframes.tentative.html": [ @@ -427695,26 +427863,18 @@ "5c5cdb42e7078b18ed1e4f58f34747ce76d50c02", "support" ], - "css/css-ui/appearance-button-bevel-001.html": [ - "03748528154acc19f6d9dc8fb00ee8423a2c60bf", - "reftest" - ], "css/css-ui/appearance-checkbox-001.html": [ "54ebef94f24cd207f1e7a3f40f45cc825698df1c", "reftest" ], "css/css-ui/appearance-cssom-001-expected.txt": [ - "30c70bbdb39d95c2ade23318f0903cf6005a970a", + "3c5f1f08b844f2915f1acad7cf75a879d7f605a4", "support" ], "css/css-ui/appearance-cssom-001.html": [ "f7dd4d1d761ed57831ae7842280f47164c6c080e", "testharness" ], - "css/css-ui/appearance-initial-value-001-expected.txt": [ - "7b676a1cf2630657c56d5a40d3582828a03ff0d5", - "support" - ], "css/css-ui/appearance-initial-value-001.html": [ "6e7d3002676d7c9a7bde572e903e5a148c5f34d5", "testharness" @@ -427739,10 +427899,6 @@ "da6f1ffa6cacd3ac0e77b343ffaa33ab44f4c2c2", "reftest" ], - "css/css-ui/appearance-parsing-expected.txt": [ - "c748b8aeb1f562e25ea64ef11239f4b670fc0759", - "support" - ], "css/css-ui/appearance-parsing.html": [ "8d6973231c0cb33fa0bd1ff83f54f98487d844e8", "testharness" @@ -427751,10 +427907,6 @@ "1573f69911566fc4410f6d49959f83dad140ce3e", "reftest" ], - "css/css-ui/appearance-property-expected.txt": [ - "90dcd4612b5f0193432bd81d19e7e89c790a9305", - "support" - ], "css/css-ui/appearance-property.html": [ "53b98ba6055f81b7dd8510cd5be5f85b1ff4a01f", "testharness" @@ -427771,10 +427923,6 @@ "78741411551c667c3f3f317eeb475db883d9d7d4", "reftest" ], - "css/css-ui/appearance-serialization-expected.txt": [ - "edcbb8b50929b54000a972029bf7c292cf4b5f9d", - "support" - ], "css/css-ui/appearance-serialization.html": [ "ed968afee609b4beab0a67d7bc9fc11c686ecb33", "testharness" @@ -428420,11 +428568,11 @@ "manual" ], "css/css-ui/inheritance-expected.txt": [ - "eb57674e25b8db519d05bb2b4b229db8e50740bf", + "548a76a3407ac8a48f9f108559957cf061f20a19", "support" ], "css/css-ui/inheritance.html": [ - "6315316d8224b7c2f3d4f575e2e48d9527a22223", + "c2aab07a23b9502353c7c3bbe798963442c651fe", "testharness" ], "css/css-ui/nav-dir-001.html": [ @@ -428948,7 +429096,7 @@ "testharness" ], "css/css-ui/parsing/outline-offset-computed.html": [ - "feb7732df35583849fb5fce78e02c8afce0de376", + "3ba35217ce1905b2e99f1a3055b169e46d4a9af3", "testharness" ], "css/css-ui/parsing/outline-offset-invalid.html": [ @@ -430391,10 +430539,6 @@ "fb0261b020f6fc2b1e3bfccb3da7d899f0337f79", "reftest" ], - "css/css-ui/webkit-appearance-button-bevel-001.html": [ - "3c860f23ae12ca204a2c76d7e181cb12c4de63c5", - "reftest" - ], "css/css-ui/webkit-appearance-checkbox-001.html": [ "09dd3d76cd66d59522b02d1b6a0c0126bb5eda2a", "reftest" @@ -430419,10 +430563,6 @@ "05fb5ce25f24df1bf8fd2c72323a9deea9d0e112", "reftest" ], - "css/css-ui/webkit-appearance-parsing-expected.txt": [ - "c748b8aeb1f562e25ea64ef11239f4b670fc0759", - "support" - ], "css/css-ui/webkit-appearance-parsing.html": [ "0f08eab222493a123fd5a44afce3689385a42390", "testharness" @@ -430431,10 +430571,6 @@ "b989502902d2b8716f7fcc0d8f18e124ec8cb94e", "reftest" ], - "css/css-ui/webkit-appearance-property-expected.txt": [ - "d0e76b0a11629e39dc97e7e3ac72e1f14132b827", - "support" - ], "css/css-ui/webkit-appearance-property.html": [ "fb3f7df2d4885c801711f91f7d1e1f7ba09a3951", "testharness" @@ -430451,10 +430587,6 @@ "8abd91e3c8faa9f5e02a8af6d2f4e66e1a0c6c29", "reftest" ], - "css/css-ui/webkit-appearance-serialization-expected.txt": [ - "3ff4fe3e611739b95b9d38a2acffbd3559d044f2", - "support" - ], "css/css-ui/webkit-appearance-serialization.html": [ "b325fd5d6c647063c880046804afbac23c617d7f", "testharness" @@ -458388,11 +458520,11 @@ "testharness" ], "fetch/origin/assorted.window-expected.txt": [ - "b5fa6b585fb29ed98beba6edbaf498c20d32544f", + "6b30c4e43e6a70892310392dada07e458e588443", "support" ], "fetch/origin/assorted.window.js": [ - "cc37dbd8ed990c60a0e9347f0f25336f2c9f70d3", + "fc6dd1a02870e29f43531821a8958b59ed6cfc1d", "testharness" ], "fetch/origin/resources/redirect-and-stash.py": [ @@ -461592,7 +461724,7 @@ "testharness" ], "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-expected.txt": [ - "4d1f8a9abd4d46f445ceb66ec1f65fe65425aabd", + "73507dc26a7a6935592a606ac49ce62bbaf4ff8c", "support" ], "html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird-expected.txt": [ @@ -463395,10 +463527,6 @@ "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8", "support" ], - "html/cross-origin-opener-policy/coep-redirect.https-expected.txt": [ - "78adc45f03aa0ba3bdc35cee22fe107ae8ce73d5", - "support" - ], "html/cross-origin-opener-policy/coep-redirect.https.html": [ "83f8f8a33d4b2c9c7f23c02011bcc568836e62ea", "testharness" @@ -470888,7 +471016,7 @@ "testharness" ], "html/rendering/widgets/appearance/default-styles-expected.txt": [ - "c5d868fd31d5b8bdcccad46343ee8083dfc7fd5d", + "7062e8d5a4ec4581085be7f9157382b64b046235", "support" ], "html/rendering/widgets/appearance/default-styles.html": [ @@ -483311,10 +483439,6 @@ "168c9e9956f9efae57d64948a34d7a24aa5bb44f", "testharness" ], - "infrastructure/testdriver/send_keys-expected.txt": [ - "fbd705a2a1403a1c6e14a3fdfb6f7cd6a7af0193", - "support" - ], "infrastructure/testdriver/send_keys.html": [ "2170347c9729564f7e492009b3d20b3267422c1d", "testharness" @@ -495124,67 +495248,75 @@ "testharness" ], "offscreen-canvas/text/2d.text.measure.actualBoundingBox.html": [ - "9b2e5eaeed34454fc77cd35a137db69a957620c6", + "8c3606be19d563c816e590e7346f8df611442863", "testharness" ], "offscreen-canvas/text/2d.text.measure.actualBoundingBox.worker.js": [ - "de9370c7d5fa225cf88f085c383a316da61ab9b8", + "4b4d859dc30ea5111335bdae491a9e6c205b34ac", "testharness" ], "offscreen-canvas/text/2d.text.measure.advances.html": [ - "aa26e529d8bc8186f113885ac6bb7a651af140a5", + "2c35113c47f934b7f1648d4b0e402130e450d2b7", "testharness" ], "offscreen-canvas/text/2d.text.measure.advances.worker.js": [ - "85fcd38089569215da97b616ed2271669865de17", + "bc111e2c3219d556c24d5a16dc665811b7257a01", "testharness" ], "offscreen-canvas/text/2d.text.measure.baselines.html": [ - "a09e9508a7c8e4338715fbd7f2b51f5542f90f36", + "2d27995407f34f00cefc2e53423fd5733c3dc242", "testharness" ], "offscreen-canvas/text/2d.text.measure.baselines.worker.js": [ - "8dbaa3b01c93e517cf5c958486e8d056aa987889", + "902e9d69549de8278c1219ec0551a99864b947e8", "testharness" ], "offscreen-canvas/text/2d.text.measure.emHeights.html": [ - "cadbce72bae4b8a972c374e6145a49cc0a8616b8", + "aadf53d7aee4e7a92d21783a4a4792e285911106", "testharness" ], "offscreen-canvas/text/2d.text.measure.emHeights.worker.js": [ - "db217e190af4c66acf9d4e17eed1300e08f2bd9a", + "86a79b5fd2709dbfcddce63c5851401a2a776e00", "testharness" ], "offscreen-canvas/text/2d.text.measure.fontBoundingBox.html": [ - "b1075b015a10a8037f532fc1afd2a1b8bbd0684e", + "c5d50acfe52129f52ba60b29c15ac0753f14d6a2", "testharness" ], "offscreen-canvas/text/2d.text.measure.fontBoundingBox.worker.js": [ - "de97ef641f1d8e959a53f44baf4dea66cb064bca", + "e3d8d88892f878902a8e365978b2e8ff82981c45", "testharness" ], "offscreen-canvas/text/2d.text.measure.width.basic.html": [ - "c7edb163d311e1dd4d245b2f37023c24374690a3", + "678a059e37288cf8f3d027b1c1156456d2fa8dcc", "testharness" ], "offscreen-canvas/text/2d.text.measure.width.basic.worker.js": [ - "11b36c082b1ec7a1e68f7d4e2262a2aeb5e302c6", + "3e1454fc87e746552863a26eaaf5761a24134458", "testharness" ], "offscreen-canvas/text/2d.text.measure.width.empty.html": [ - "b1044623b2441842c151f44a5171f3e53e27d773", + "304d6b2248e8aedc0b30c6f15bbbec96cc4c9559", "testharness" ], "offscreen-canvas/text/2d.text.measure.width.empty.worker.js": [ - "124353c5afc1d5e273a23e3ddd13d67929ef5b4d", + "7dd1677b96497bfeacb2c81d74d628af6c0f2ea0", "testharness" ], + "offscreen-canvas/text/2d.text.measure.width.space-expected.txt": [ + "fa0b0b36605c4be0235f178a9fe354aa7068acd4", + "support" + ], "offscreen-canvas/text/2d.text.measure.width.space.html": [ - "b3cb2fc4420d69692effc54b19e788391e9e28ef", + "b452fc98b6b567dd7ee4a286d3bbce99cddc076e", "testharness" ], + "offscreen-canvas/text/2d.text.measure.width.space.worker-expected.txt": [ + "fa0b0b36605c4be0235f178a9fe354aa7068acd4", + "support" + ], "offscreen-canvas/text/2d.text.measure.width.space.worker.js": [ - "a1232dd4f79d29380b0cf93a0cc08bffde00e352", + "3d78110f7e636cdeb02dc75d3f35d1410fd4c0c2", "testharness" ], "offscreen-canvas/the-canvas-state/2d.state.saverestore.bitmap.html": [ @@ -495796,7 +495928,7 @@ "support" ], "offscreen-canvas/tools/tests2d.yaml": [ - "1d2e1210ed180903ab40a6bbf205ca076d65835d", + "846dc8b3eedc80171b4ea103b936eaa863b81d6c", "support" ], "offscreen-canvas/transformations/2d.transformation.getTransform.html": [ @@ -506000,7 +506132,7 @@ "reftest" ], "scroll-animations/constructor-expected.txt": [ - "dd1ea00be1f1616790a4ac6aed26d6817246a942", + "f52fddfbf134a724704b4ddc63dd27289bb6ebd2", "support" ], "scroll-animations/constructor-no-document.html": [ @@ -506008,7 +506140,7 @@ "testharness" ], "scroll-animations/constructor.html": [ - "5d13035f6a1f527c2467f5768908e6b27eda6995", + "7cb7013c00685aa07f2a5a4acee22365a5d08293", "testharness" ], "scroll-animations/current-time-nan.html": [ @@ -507856,11 +507988,11 @@ "testharness" ], "service-workers/service-worker/fetch-event-handled.https-expected.txt": [ - "42484619e33308d010376fec1eda99c0bdea03c3", + "9b071f9be6e590d23cd8d645aa12789985137c74", "support" ], "service-workers/service-worker/fetch-event-handled.https.html": [ - "2d6f6c86d876daf40ea8f41be01bca2c549bcc41", + "89f3d79a681a22cfd6889b3c0603f7388d460472", "testharness" ], "service-workers/service-worker/fetch-event-is-history-backward-navigation-manual.https.html": [ @@ -508796,7 +508928,7 @@ "support" ], "service-workers/service-worker/resources/fetch-event-handled-worker.js": [ - "4af58e20d05c902d74511579e6b74894731d1239", + "0dc6de005dba08cda134aa657e56191362cf28a8", "support" ], "service-workers/service-worker/resources/fetch-event-network-error-controllee-iframe.html": [ @@ -523672,7 +523804,7 @@ "support" ], "web-animations/animation-model/animation-types/accumulation-per-property-expected.txt": [ - "9b5d78ab275ad7a9946a2462afa077a40de644bb", + "0ad89a6b96968712b74d6590f7ab1b1c434073d8", "support" ], "web-animations/animation-model/animation-types/accumulation-per-property.html": [ @@ -523680,7 +523812,7 @@ "testharness" ], "web-animations/animation-model/animation-types/addition-per-property-expected.txt": [ - "665b9fb2227ee2b685c9e9a0fab39f8702a807aa", + "270f0db112d0b70def52c58034a834e35933e317", "support" ], "web-animations/animation-model/animation-types/addition-per-property.html": [ @@ -523692,7 +523824,7 @@ "testharness" ], "web-animations/animation-model/animation-types/interpolation-per-property-expected.txt": [ - "b17015724a58e39da178dbc17300a7d8ed29ad0d", + "265d5bc2d09edeaa2b1fa96f960cd0647e05d403", "support" ], "web-animations/animation-model/animation-types/interpolation-per-property.html": [ @@ -525615,12 +525747,8 @@ "46cab3051b4924a2cb9cf1d7a2df46046b7b2f23", "testharness" ], - "webauthn/createcredential-passing.https-expected.txt": [ - "39540b29c138f85bbe878dd7382664eff254734b", - "support" - ], "webauthn/createcredential-passing.https.html": [ - "a94be363da20214ac84950b2bb701d428372dd10", + "30fef13bbdc9efb5659460652054d119399ce819", "testharness" ], "webauthn/createcredential-pubkeycredparams.https.html": [ @@ -525639,12 +525767,8 @@ "7f8571586e4094e663399b79f473676cdfb0a660", "testharness" ], - "webauthn/getcredential-extensions.https-expected.txt": [ - "402ef6fc2d0de20ff07ad071dab8377e304eb657", - "support" - ], "webauthn/getcredential-extensions.https.html": [ - "820f9b529f16e5644d3d288f406db6e71a72cf34", + "af03086ee048567c32338636560ff2d76351892b", "testharness" ], "webauthn/getcredential-passing.https.html": [ @@ -527519,6 +527643,22 @@ "8c7bf665ef69487f396519e9e6b45a010854bb3a", "testharness" ], + "webrtc-insertable-streams/RTCEncodedAudioFrame-serviceworker-failure.https.html": [ + "fda89f36dcb52668e28d8c017112f6efb1f169a8", + "testharness" + ], + "webrtc-insertable-streams/RTCEncodedVideoFrame-serviceworker-failure.https.html": [ + "93b9a6a0f36098e3d20762adc9e1d30b61fc7b15", + "testharness" + ], + "webrtc-insertable-streams/resources/blank.html": [ + "a3c3a4689a62b45b1e429f6b7a94690e556a1259", + "support" + ], + "webrtc-insertable-streams/resources/serviceworker-failure.js": [ + "e7aa8e11be396cc32eda592ae9618391ad6fee40", + "support" + ], "webrtc-quic/META.yml": [ "740c8d2fe84beafbcb7f98cef29aff2378721132", "support" @@ -528220,7 +528360,7 @@ "support" ], "webrtc/idlharness.https.window.js": [ - "93341278ac628f7ecc514283f01ad6d9ad90bc28", + "ae18cc6353831a8c18928f1e68e6a80ac400bb0d", "testharness" ], "webrtc/legacy/README.txt": [ @@ -528323,6 +528463,18 @@ "291437a526582d13db6e04fa39c152ce9ed5859a", "testharness" ], + "webrtc/simulcast/.eslintignore": [ + "90fee69f044fc5adfcf49bac0fdb6dcd638556e1", + "support" + ], + "webrtc/simulcast/basic.https.html": [ + "ae2e7eec11b85bb0f5b0444e6e6cf7123e7e26e0", + "testharness" + ], + "webrtc/simulcast/simulcast.js": [ + "ed08ddca44866367bd66ea3b5a7c3a6f58a85f03", + "support" + ], "webrtc/third_party/README.md": [ "56a2295dd103db76836d17fa513f56d09891c586", "support"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-size-002.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-size-002.html new file mode 100644 index 0000000..41a8cd7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-size-002.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>CSS Flexbox: min-size when the child has a percentage min-size</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#algo-main-item"> +<meta name="assert" content="This test ensures that min-size can not be negative when the child has a percentage min-size."> +<link href="support/flexbox.css" rel="stylesheet"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<body onload="checkLayout('.flexbox')"> +<div id=log></div> + +<div class="flexbox column" style="max-height: 0; overflow: hidden; line-height: 13px;" data-expected-height="0"> + <div style="min-height: 100%;" data-expected-height="0">This is a flex item.</div> + <div style="flex: none;" data-expected-height="13">Inflexible</div> +</div>
diff --git a/third_party/blink/web_tests/css3/flexbox/stretch-input-in-column-expected.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/stretch-input-in-column-ref.html similarity index 77% rename from third_party/blink/web_tests/css3/flexbox/stretch-input-in-column-expected.html rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/stretch-input-in-column-ref.html index bdf8519..85d2a49e 100644 --- a/third_party/blink/web_tests/css3/flexbox/stretch-input-in-column-expected.html +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/reference/stretch-input-in-column-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <html> -<link rel="stylesheet" href="resources/flexbox.css"> +<link href="../support/flexbox.css" rel="stylesheet"> <style> .flexbox { background-color: grey; @@ -10,7 +10,7 @@ } </style> <body> -<p>Form controls that are stretched in a column flexbox should not overflow the flexbox.</p> +<p>This test passes if none of the form controls overflow.</p> <div class="flexbox"> <input> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/stretch-input-in-column.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/stretch-input-in-column.html new file mode 100644 index 0000000..4136c45 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/stretch-input-in-column.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<title>CSS Flexbox: Stretch input form controls in flexbox column</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-property"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#align-items-property"> +<link rel="match" href="reference/stretch-input-in-column-ref.html"> +<link href="support/flexbox.css" rel="stylesheet"> +<meta name="assert" content="This test ensures that input form controls that are stretched in +a column flexbox should not overflow the flexbox."> +<style> +.flexbox { + background-color: grey; +} +</style> +<body> +<p>This test passes if none of the form controls overflow.</p> +<div class="flexbox column"> + <input> +</div> +<div class="flexbox column align-content-flex-start"> + <textarea class="align-self-stretch"></textarea> +</div> +<div class="flexbox column wrap"> + <input type="button"> +</div> +<div class="flexbox column"> + <select></select> +</div> +<div class="flexbox column"> + <legend style="border: 2px solid black">legend</legend> +</div> +<div class="flexbox column wrap"> + <div type="border: 4px solid black; padding: 10px;"> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip-ref.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip-ref.html new file mode 100644 index 0000000..c061a1d6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip-ref.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> +.multicol { + column-count: 3; +} +.parent { + background: green; + height: 50px; +} +</style> +<div class="multicol"> + <div class="parent"></div> + <div class="parent"></div> + <div class="parent"></div> +</div> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip.html new file mode 100644 index 0000000..af59ff9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-overflow-clip.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<title>CSS Multi-column Layout Test: multicol with overflow-clipped content</title> +<link rel="help" href="https://www.w3.org/TR/css-multicol-1/"> +<link rel="match" href="multicol-overflow-clip-ref.html"> +<meta name="assert" content="Overflow clip should work under multicol."> +<style> +.multicol { + column-count: 3; +} +.parent { + background: green; + height: 50px; + overflow: hidden; +} +.child2 { + margin-top: 50px; + background: darkred; + color: red; + height: 100px; +} +</style> +<div class="multicol"> + <div class="parent"> + <div class="child2">This should be hidden.</div> + </div> + <div class="parent"> + <div class="child2">This should be hidden.</div> + </div> + <div class="parent"> + <div class="child2">This should be hidden.</div> + </div> +</div> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-button-bevel-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-button-bevel-001.html deleted file mode 100644 index 0374852..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-button-bevel-001.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: appearance: button-bevel</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="button-bevel is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { appearance: none; appearance: button-bevel; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001-expected.txt index 30c70bbd..3c5f1f0 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 342 tests; 170 PASS, 172 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 342 tests; 324 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS -webkit-appearance: none PASS -webkit-appearance: auto PASS -webkit-appearance: button @@ -163,169 +163,169 @@ PASS -webkit-appearance: -moz-window-frame-right (invalid) PASS -webkit-appearance: -moz-window-titlebar (invalid) PASS -webkit-appearance: -moz-window-titlebar-maximized (invalid) -FAIL appearance: none assert_equals: style.appearance expected (string) "none" but got (undefined) undefined -FAIL appearance: auto assert_equals: style.appearance expected (string) "auto" but got (undefined) undefined -FAIL appearance: button assert_equals: style.appearance expected (string) "button" but got (undefined) undefined -FAIL appearance: checkbox assert_equals: style.appearance expected (string) "checkbox" but got (undefined) undefined -FAIL appearance: listbox assert_equals: style.appearance expected (string) "listbox" but got (undefined) undefined -FAIL appearance: menulist assert_equals: style.appearance expected (string) "menulist" but got (undefined) undefined -FAIL appearance: menulist-button assert_equals: style.appearance expected (string) "menulist-button" but got (undefined) undefined -FAIL appearance: meter assert_equals: style.appearance expected (string) "meter" but got (undefined) undefined -FAIL appearance: progress-bar assert_equals: style.appearance expected (string) "progress-bar" but got (undefined) undefined -FAIL appearance: push-button assert_equals: style.appearance expected (string) "push-button" but got (undefined) undefined -FAIL appearance: radio assert_equals: style.appearance expected (string) "radio" but got (undefined) undefined -FAIL appearance: searchfield assert_equals: style.appearance expected (string) "searchfield" but got (undefined) undefined -FAIL appearance: slider-horizontal assert_equals: style.appearance expected (string) "slider-horizontal" but got (undefined) undefined -FAIL appearance: square-button assert_equals: style.appearance expected (string) "square-button" but got (undefined) undefined -FAIL appearance: textarea assert_equals: style.appearance expected (string) "textarea" but got (undefined) undefined -FAIL appearance: textfield assert_equals: style.appearance expected (string) "textfield" but got (undefined) undefined -FAIL appearance: bogus-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: attachment (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-bevel (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: borderless-attachment (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-arrow-down (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-arrow-next (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-arrow-previous (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-arrow-up (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: button-focus (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: caps-lock-indicator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: caret (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: checkbox-container (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: checkbox-label (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: checkmenuitem (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: color-well (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: continuous-capacity-level-indicator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: default-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: discrete-capacity-level-indicator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: dualbutton (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: groupbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: image-controls-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: inner-spin-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: list-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: listitem (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-controls-background (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-controls-dark-bar-background (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-controls-fullscreen-background (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-controls-light-bar-background (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-current-time-display (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-enter-fullscreen-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-exit-fullscreen-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-fullscreen-volume-slider (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-fullscreen-volume-slider-thumb (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-mute-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-overlay-play-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-play-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-return-to-realtime-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-rewind-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-seek-back-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-seek-forward-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-slider (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-sliderthumb (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-time-remaining-display (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-toggle-closed-captions-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-volume-slider (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-volume-slider-container (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-volume-slider-mute-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: media-volume-sliderthumb (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuarrow (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menubar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menucheckbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuimage (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuitem (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuitemtext (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menulist-text (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menulist-textfield (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menupopup (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuradio (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: menuseparator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: meterbar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: meterchunk (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: number-input (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: progress-bar-value (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: progressbar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: progressbar-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: progresschunk (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: progresschunk-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: radio-container (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: radio-label (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: radiomenuitem (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: range (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: range-thumb (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: rating-level-indicator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: relevancy-level-indicator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: resizer (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: resizerpanel (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scale-horizontal (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scale-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scalethumb-horizontal (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scalethumb-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scalethumbend (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scalethumbstart (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scalethumbtick (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarbutton-down (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarbutton-left (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarbutton-right (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarbutton-up (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarthumb-horizontal (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbarthumb-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbartrack-horizontal (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: scrollbartrack-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: searchfield-cancel-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: searchfield-decoration (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: searchfield-results-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: searchfield-results-decoration (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: separator (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: sheet (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: slider-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: sliderthumb-horizontal (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: sliderthumb-vertical (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: snapshotted-plugin-overlay (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: spinner (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: spinner-downbutton (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: spinner-textfield (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: spinner-upbutton (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: splitter (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: statusbar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: statusbarpanel (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tab (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tab-scroll-arrow-back (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tab-scroll-arrow-forward (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tabpanel (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tabpanels (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: textfield-multiline (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: toolbar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: toolbarbutton (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: toolbarbutton-dropdown (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: toolbargripper (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: toolbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: tooltip (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeheader (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeheadercell (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeheadersortarrow (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeitem (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeline (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treetwisty (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treetwistyopen (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: treeview (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -apple-pay-button (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-borderless-glass (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-browsertabbar-toolbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-communications-toolbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-communicationstext (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-exclude-glass (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-glass (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-win-media-toolbox (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-box (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-box-maximized (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-close (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-maximize (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-minimize (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-button-restore (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-frame-bottom (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-frame-left (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-frame-right (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-titlebar (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined -FAIL appearance: -moz-window-titlebar-maximized (invalid) assert_equals: style.appearance expected (string) "" but got (undefined) undefined +PASS appearance: none +PASS appearance: auto +PASS appearance: button +PASS appearance: checkbox +PASS appearance: listbox +PASS appearance: menulist +PASS appearance: menulist-button +PASS appearance: meter +PASS appearance: progress-bar +PASS appearance: push-button +PASS appearance: radio +PASS appearance: searchfield +PASS appearance: slider-horizontal +PASS appearance: square-button +PASS appearance: textarea +PASS appearance: textfield +PASS appearance: bogus-button (invalid) +PASS appearance: attachment (invalid) +PASS appearance: button-bevel (invalid) +PASS appearance: borderless-attachment (invalid) +PASS appearance: button-arrow-down (invalid) +PASS appearance: button-arrow-next (invalid) +PASS appearance: button-arrow-previous (invalid) +PASS appearance: button-arrow-up (invalid) +PASS appearance: button-focus (invalid) +PASS appearance: caps-lock-indicator (invalid) +PASS appearance: caret (invalid) +PASS appearance: checkbox-container (invalid) +PASS appearance: checkbox-label (invalid) +PASS appearance: checkmenuitem (invalid) +PASS appearance: color-well (invalid) +PASS appearance: continuous-capacity-level-indicator (invalid) +PASS appearance: default-button (invalid) +PASS appearance: discrete-capacity-level-indicator (invalid) +PASS appearance: dualbutton (invalid) +PASS appearance: groupbox (invalid) +PASS appearance: image-controls-button (invalid) +FAIL appearance: inner-spin-button (invalid) assert_equals: style.appearance expected "" but got "inner-spin-button" +PASS appearance: list-button (invalid) +PASS appearance: listitem (invalid) +PASS appearance: media-controls-background (invalid) +PASS appearance: media-controls-dark-bar-background (invalid) +PASS appearance: media-controls-fullscreen-background (invalid) +PASS appearance: media-controls-light-bar-background (invalid) +PASS appearance: media-current-time-display (invalid) +PASS appearance: media-enter-fullscreen-button (invalid) +PASS appearance: media-exit-fullscreen-button (invalid) +PASS appearance: media-fullscreen-volume-slider (invalid) +PASS appearance: media-fullscreen-volume-slider-thumb (invalid) +PASS appearance: media-mute-button (invalid) +PASS appearance: media-overlay-play-button (invalid) +PASS appearance: media-play-button (invalid) +PASS appearance: media-return-to-realtime-button (invalid) +PASS appearance: media-rewind-button (invalid) +PASS appearance: media-seek-back-button (invalid) +PASS appearance: media-seek-forward-button (invalid) +FAIL appearance: media-slider (invalid) assert_equals: style.appearance expected "" but got "media-slider" +FAIL appearance: media-sliderthumb (invalid) assert_equals: style.appearance expected "" but got "media-sliderthumb" +PASS appearance: media-time-remaining-display (invalid) +PASS appearance: media-toggle-closed-captions-button (invalid) +FAIL appearance: media-volume-slider (invalid) assert_equals: style.appearance expected "" but got "media-volume-slider" +PASS appearance: media-volume-slider-container (invalid) +PASS appearance: media-volume-slider-mute-button (invalid) +FAIL appearance: media-volume-sliderthumb (invalid) assert_equals: style.appearance expected "" but got "media-volume-sliderthumb" +PASS appearance: menuarrow (invalid) +PASS appearance: menubar (invalid) +PASS appearance: menucheckbox (invalid) +PASS appearance: menuimage (invalid) +PASS appearance: menuitem (invalid) +PASS appearance: menuitemtext (invalid) +PASS appearance: menulist-text (invalid) +PASS appearance: menulist-textfield (invalid) +PASS appearance: menupopup (invalid) +PASS appearance: menuradio (invalid) +PASS appearance: menuseparator (invalid) +PASS appearance: meterbar (invalid) +PASS appearance: meterchunk (invalid) +PASS appearance: number-input (invalid) +PASS appearance: progress-bar-value (invalid) +PASS appearance: progressbar (invalid) +PASS appearance: progressbar-vertical (invalid) +PASS appearance: progresschunk (invalid) +PASS appearance: progresschunk-vertical (invalid) +PASS appearance: radio-container (invalid) +PASS appearance: radio-label (invalid) +PASS appearance: radiomenuitem (invalid) +PASS appearance: range (invalid) +PASS appearance: range-thumb (invalid) +PASS appearance: rating-level-indicator (invalid) +PASS appearance: relevancy-level-indicator (invalid) +PASS appearance: resizer (invalid) +PASS appearance: resizerpanel (invalid) +PASS appearance: scale-horizontal (invalid) +PASS appearance: scale-vertical (invalid) +PASS appearance: scalethumb-horizontal (invalid) +PASS appearance: scalethumb-vertical (invalid) +PASS appearance: scalethumbend (invalid) +PASS appearance: scalethumbstart (invalid) +PASS appearance: scalethumbtick (invalid) +PASS appearance: scrollbarbutton-down (invalid) +PASS appearance: scrollbarbutton-left (invalid) +PASS appearance: scrollbarbutton-right (invalid) +PASS appearance: scrollbarbutton-up (invalid) +PASS appearance: scrollbarthumb-horizontal (invalid) +PASS appearance: scrollbarthumb-vertical (invalid) +PASS appearance: scrollbartrack-horizontal (invalid) +PASS appearance: scrollbartrack-vertical (invalid) +FAIL appearance: searchfield-cancel-button (invalid) assert_equals: style.appearance expected "" but got "searchfield-cancel-button" +PASS appearance: searchfield-decoration (invalid) +PASS appearance: searchfield-results-button (invalid) +PASS appearance: searchfield-results-decoration (invalid) +PASS appearance: separator (invalid) +PASS appearance: sheet (invalid) +FAIL appearance: slider-vertical (invalid) assert_equals: style.appearance expected "" but got "slider-vertical" +FAIL appearance: sliderthumb-horizontal (invalid) assert_equals: style.appearance expected "" but got "sliderthumb-horizontal" +FAIL appearance: sliderthumb-vertical (invalid) assert_equals: style.appearance expected "" but got "sliderthumb-vertical" +PASS appearance: snapshotted-plugin-overlay (invalid) +PASS appearance: spinner (invalid) +PASS appearance: spinner-downbutton (invalid) +PASS appearance: spinner-textfield (invalid) +PASS appearance: spinner-upbutton (invalid) +PASS appearance: splitter (invalid) +PASS appearance: statusbar (invalid) +PASS appearance: statusbarpanel (invalid) +PASS appearance: tab (invalid) +PASS appearance: tab-scroll-arrow-back (invalid) +PASS appearance: tab-scroll-arrow-forward (invalid) +PASS appearance: tabpanel (invalid) +PASS appearance: tabpanels (invalid) +PASS appearance: textfield-multiline (invalid) +PASS appearance: toolbar (invalid) +PASS appearance: toolbarbutton (invalid) +PASS appearance: toolbarbutton-dropdown (invalid) +PASS appearance: toolbargripper (invalid) +PASS appearance: toolbox (invalid) +PASS appearance: tooltip (invalid) +PASS appearance: treeheader (invalid) +PASS appearance: treeheadercell (invalid) +PASS appearance: treeheadersortarrow (invalid) +PASS appearance: treeitem (invalid) +PASS appearance: treeline (invalid) +PASS appearance: treetwisty (invalid) +PASS appearance: treetwistyopen (invalid) +PASS appearance: treeview (invalid) +PASS appearance: -apple-pay-button (invalid) +PASS appearance: -moz-win-borderless-glass (invalid) +PASS appearance: -moz-win-browsertabbar-toolbox (invalid) +PASS appearance: -moz-win-communications-toolbox (invalid) +PASS appearance: -moz-win-communicationstext (invalid) +PASS appearance: -moz-win-exclude-glass (invalid) +PASS appearance: -moz-win-glass (invalid) +PASS appearance: -moz-win-media-toolbox (invalid) +PASS appearance: -moz-window-button-box (invalid) +PASS appearance: -moz-window-button-box-maximized (invalid) +PASS appearance: -moz-window-button-close (invalid) +PASS appearance: -moz-window-button-maximize (invalid) +PASS appearance: -moz-window-button-minimize (invalid) +PASS appearance: -moz-window-button-restore (invalid) +PASS appearance: -moz-window-frame-bottom (invalid) +PASS appearance: -moz-window-frame-left (invalid) +PASS appearance: -moz-window-frame-right (invalid) +PASS appearance: -moz-window-titlebar (invalid) +PASS appearance: -moz-window-titlebar-maximized (invalid) PASS -ms-appearance (should not be supported) PASS mso-appearance (should not be supported) PASS -moz-appearance (should not be supported)
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-initial-value-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-initial-value-001-expected.txt deleted file mode 100644 index 7b676a1..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-initial-value-001-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -FAIL support for appearance assert_equals: expected "button" but got "" -FAIL initial value for appearance assert_equals: expected "none" but got "" -PASS support for -webkit-appearance -PASS initial value for -webkit-appearance -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt deleted file mode 100644 index c748b8a..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-parsing-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL parsing via attribute change steps of CSS declaration block's owner node assert_equals: expected "none" but got "" -FAIL parsing via modification of cssText assert_equals: expected "none" but got "" -FAIL parsing via creation of CSS declaration block assert_equals: expected "none" but got "" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt deleted file mode 100644 index 90dcd46..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-property-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -FAIL setProperty assert_equals: expected (string) "none" but got (undefined) undefined -FAIL removeProperty assert_equals: expected (string) "" but got (undefined) undefined -PASS property assignment -FAIL getPropertyValue assert_equals: expected "none" but got "" -FAIL property access assert_equals: expected (string) "none" but got (undefined) undefined -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt deleted file mode 100644 index edcbb8b..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-serialization-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL serialization via CSSStyleDeclaration assert_equals: expected "appearance: none;" but got "" -FAIL serialization via CSSStyleRule assert_equals: expected "#foo { appearance: none; }" but got "#foo { }" -FAIL serialization via CSSMediaRule assert_equals: expected "@media print {\n #foo { appearance: none; }\n}" but got "@media print {\n #foo { }\n}" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance-expected.txt index eb57674..548a76a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. -FAIL Property appearance has initial value auto assert_true: appearance doesn't seem to be supported in the computed style expected true got false -FAIL Property appearance does not inherit assert_true: expected true got false +PASS Property appearance has initial value none +PASS Property appearance does not inherit PASS Property caret-color has initial value rgb(0, 255, 0) PASS Property caret-color inherits FAIL Property caret-shape has initial value auto assert_true: caret-shape doesn't seem to be supported in the computed style expected true got false
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance.html index 6315316..c2aab07 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance.html +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/inheritance.html
@@ -33,7 +33,7 @@ const mediumWidth = getComputedStyle(reference).borderTopWidth; // e.g. 3px const currentColor = getComputedStyle(reference).color; -assert_not_inherited('appearance', 'auto', 'none'); +assert_not_inherited('appearance', 'none', 'auto'); assert_inherited('caret-color', currentColor, 'rgba(42, 53, 64, 0.75)'); assert_inherited('caret-shape', 'auto', 'bar'); assert_inherited('cursor', 'auto', 'pointer');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-button-bevel-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-button-bevel-001.html deleted file mode 100644 index 3c860f23..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-button-bevel-001.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- DO NOT EDIT THIS FILE. -Edit the appearance-* file instead and then run: - ./tools/appearance-build-webkit-reftests.py ---> -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: -webkit-appearance: button-bevel</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="button-bevel is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { -webkit-appearance: none; -webkit-appearance: button-bevel; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt deleted file mode 100644 index c748b8a..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-parsing-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL parsing via attribute change steps of CSS declaration block's owner node assert_equals: expected "none" but got "" -FAIL parsing via modification of cssText assert_equals: expected "none" but got "" -FAIL parsing via creation of CSS declaration block assert_equals: expected "none" but got "" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt deleted file mode 100644 index d0e76b0..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-property-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -This is a testharness.js-based test. -FAIL setProperty - CSS property name assert_equals: expected (string) "none" but got (undefined) undefined -FAIL setProperty - camel-cased property name (ignored) assert_equals: expected (string) "" but got (undefined) undefined -FAIL setProperty - webkit-cased property name (ignored) assert_equals: expected (string) "" but got (undefined) undefined -FAIL removeProperty - CSS property name assert_equals: expected (string) "" but got (undefined) undefined -FAIL removeProperty - camel-cased property name (ignored) assert_equals: expected (string) "none" but got (undefined) undefined -FAIL removeProperty - webkit-cased property name (ignored) assert_equals: expected (string) "none" but got (undefined) undefined -FAIL property assignment - CSS property name assert_equals: expected (string) "none" but got (undefined) undefined -FAIL property assignment - camel-cased property name assert_equals: expected (string) "none" but got (undefined) undefined -FAIL property assignment - webkit-cased property name assert_equals: expected (string) "none" but got (undefined) undefined -FAIL getPropertyValue - CSS property name assert_equals: expected "none" but got "" -PASS getPropertyValue - camel-cased property name (ignored) -PASS getPropertyValue - webkit-cased property name (ignored) -FAIL property access - CSS property name assert_equals: expected "none" but got "" -FAIL property access - camel-cased property name assert_equals: expected "none" but got "" -FAIL property access - webkit-cased property name assert_equals: expected "none" but got "" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt deleted file mode 100644 index 3ff4fe3e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-serialization-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL serialization via CSSStyleDeclaration assert_equals: expected "appearance: none;" but got "-webkit-appearance: none;" -FAIL serialization via CSSStyleRule assert_equals: expected "#foo { appearance: none; }" but got "#foo { -webkit-appearance: none; }" -FAIL serialization via CSSMediaRule assert_equals: expected "@media print {\n #foo { appearance: none; }\n}" but got "@media print {\n #foo { -webkit-appearance: none; }\n}" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window-expected.txt index b5fa6b5..6b30c4e4 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window-expected.txt
@@ -4,33 +4,43 @@ PASS Origin header and POST navigation PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer FAIL Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" -PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer +FAIL Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer PASS Origin header and POST same-origin navigation with Referrer-Policy same-origin PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy same-origin PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy same-origin PASS Origin header and POST cross-origin navigation with Referrer-Policy same-origin FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy same-origin assert_equals: expected "null" but got "http://web-platform.test:8001" PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy same-origin PASS Origin header and POST same-origin navigation with Referrer-Policy origin-when-cross-origin PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin PASS Origin header and POST cross-origin navigation with Referrer-Policy origin-when-cross-origin PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade PASS Origin header and POST same-origin navigation with Referrer-Policy unsafe-url PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy unsafe-url PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy unsafe-url PASS Origin header and POST cross-origin navigation with Referrer-Policy unsafe-url PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy unsafe-url PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy unsafe-url Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window.js b/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window.js index cc37dbd..fc6dd1a 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window.js +++ b/third_party/blink/web_tests/external/wpt/fetch/origin/assorted.window.js
@@ -115,7 +115,7 @@ }; } -function fetchReferrerPolicy(referrerPolicy, destination, fetchMode, expectedOrigin) { +function fetchReferrerPolicy(referrerPolicy, destination, fetchMode, expectedOrigin, httpMethod) { return async function () { const stash = token(); const redirectPath = "/fetch/origin/resources/redirect-and-stash.py"; @@ -125,7 +125,7 @@ : origins.HTTP_REMOTE_ORIGIN) + redirectPath + "?stash=" + stash; - await fetch(fetchUrl, { mode: fetchMode, method: "POST" , "referrerPolicy": referrerPolicy}); + await fetch(fetchUrl, { mode: fetchMode, method: httpMethod , "referrerPolicy": referrerPolicy}); const json = await (await fetch(redirectPath + "?dump&stash=" + stash)).json(); @@ -133,8 +133,8 @@ }; } -function referrerPolicyTestString(referrerPolicy, destination) { - return "Origin header and POST " + destination + " with Referrer-Policy " + +function referrerPolicyTestString(referrerPolicy, method, destination) { + return "Origin header and " + method + " " + destination + " with Referrer-Policy " + referrerPolicy; } @@ -179,23 +179,33 @@ promise_test(navigationReferrerPolicy(testObj.policy, destination.name, destination.expectedOrigin), - referrerPolicyTestString(testObj.policy, + referrerPolicyTestString(testObj.policy, "POST", destination.name + " navigation")); // Test fetch promise_test(fetchReferrerPolicy(testObj.policy, destination.name, "no-cors", - destination.expectedOrigin), - referrerPolicyTestString(testObj.policy, + destination.expectedOrigin, + "POST"), + referrerPolicyTestString(testObj.policy, "POST", destination.name + " fetch no-cors mode")); - // When we're dealing with CORS (mode is "cors"), we shouldn't take the - // Referrer-Policy into account + // Test cors mode POST promise_test(fetchReferrerPolicy(testObj.policy, destination.name, "cors", - origins.HTTP_ORIGIN), - referrerPolicyTestString(testObj.policy, + (destination.name == "same-origin") ? destination.expectedOrigin : origins.HTTP_ORIGIN, + "POST"), + referrerPolicyTestString(testObj.policy, "POST", + destination.name + " fetch cors mode")); + + // Test cors mode GET + promise_test(fetchReferrerPolicy(testObj.policy, + destination.name, + "cors", + (destination.name == "same-origin") ? "no Origin header" : origins.HTTP_ORIGIN, + "GET"), + referrerPolicyTestString(testObj.policy, "GET", destination.name + " fetch cors mode")); }); });
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/appearance/default-styles-expected.txt b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/appearance/default-styles-expected.txt index c5d868f..7062e8d 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/appearance/default-styles-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/appearance/default-styles-expected.txt
@@ -28,21 +28,21 @@ FAIL <textarea> assert_equals: -webkit-appearance expected "auto" but got "textarea" FAIL <meter> assert_equals: -webkit-appearance expected "auto" but got "meter" FAIL <progress> assert_equals: -webkit-appearance expected "auto" but got "progress-bar" -FAIL <input type="hidden"> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <input type="HIDDEN"> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <input type="file"> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <input type="image"> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <div> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <details> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <summary> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <video> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <video controls=""> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <menuitem> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <marquee> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <keygen> assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <input> (namespace: null) assert_equals: appearance (no prefix) expected "none" but got "" -FAIL <input> (namespace: http://www.w3.org/2000/svg) assert_equals: appearance (no prefix) expected "none" but got "" -FAIL The html element assert_equals: appearance (no prefix) expected "none" but got "" -FAIL The body element assert_equals: appearance (no prefix) expected "none" but got "" +PASS <input type="hidden"> +PASS <input type="HIDDEN"> +PASS <input type="file"> +PASS <input type="image"> +PASS <div> +PASS <details> +PASS <summary> +PASS <video> +PASS <video controls=""> +PASS <menuitem> +PASS <marquee> +PASS <keygen> +PASS <input> (namespace: null) +PASS <input> (namespace: http://www.w3.org/2000/svg) +PASS The html element +PASS The body element Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002-expected.txt new file mode 100644 index 0000000..fd33b8b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/border-002-expected.txt
@@ -0,0 +1,52 @@ +This is a testharness.js-based test. +PASS Border properties on maction +PASS Border properties on maction (rtl) +PASS Border properties on menclose +PASS Border properties on menclose (rtl) +PASS Border properties on merror +PASS Border properties on merror (rtl) +PASS Border properties on mfrac +PASS Border properties on mfrac (rtl) +PASS Border properties on mi +PASS Border properties on mi (rtl) +PASS Border properties on mmultiscripts +PASS Border properties on mmultiscripts (rtl) +PASS Border properties on mn +PASS Border properties on mn (rtl) +PASS Border properties on mo +PASS Border properties on mo (rtl) +PASS Border properties on mover +PASS Border properties on mover (rtl) +PASS Border properties on mpadded +PASS Border properties on mpadded (rtl) +PASS Border properties on mphantom +PASS Border properties on mphantom (rtl) +FAIL Border properties on mroot assert_true: mroot is supported expected true got false +FAIL Border properties on mroot (rtl) assert_true: mroot is supported expected true got false +PASS Border properties on mrow +PASS Border properties on mrow (rtl) +PASS Border properties on ms +PASS Border properties on ms (rtl) +PASS Border properties on mspace +FAIL Border properties on msqrt assert_true: msqrt is supported expected true got false +FAIL Border properties on msqrt (rtl) assert_true: msqrt is supported expected true got false +PASS Border properties on mstyle +PASS Border properties on mstyle (rtl) +PASS Border properties on msub +PASS Border properties on msub (rtl) +PASS Border properties on msubsup +PASS Border properties on msubsup (rtl) +PASS Border properties on msup +PASS Border properties on msup (rtl) +PASS Border properties on mtable +PASS Border properties on mtable (rtl) +PASS Border properties on mtext +PASS Border properties on mtext (rtl) +PASS Border properties on munder +PASS Border properties on munder (rtl) +PASS Border properties on munderover +PASS Border properties on munderover (rtl) +PASS Border properties on semantics +PASS Border properties on semantics (rtl) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002-expected.txt new file mode 100644 index 0000000..12188ba61 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-002-expected.txt
@@ -0,0 +1,77 @@ +This is a testharness.js-based test. +Found 73 tests; 67 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Margin properties on maction +PASS Margin properties on maction (rtl) +PASS Margin properties on maction (no margin-collapsing) +PASS Margin properties on menclose +PASS Margin properties on menclose (rtl) +PASS Margin properties on menclose (no margin-collapsing) +PASS Margin properties on merror +PASS Margin properties on merror (rtl) +PASS Margin properties on merror (no margin-collapsing) +PASS Margin properties on mfrac +PASS Margin properties on mfrac (rtl) +PASS Margin properties on mfrac (no margin-collapsing) +PASS Margin properties on mi +PASS Margin properties on mi (rtl) +PASS Margin properties on mi (no margin-collapsing) +PASS Margin properties on mmultiscripts +PASS Margin properties on mmultiscripts (rtl) +PASS Margin properties on mmultiscripts (no margin-collapsing) +PASS Margin properties on mn +PASS Margin properties on mn (rtl) +PASS Margin properties on mn (no margin-collapsing) +PASS Margin properties on mo +PASS Margin properties on mo (rtl) +PASS Margin properties on mo (no margin-collapsing) +PASS Margin properties on mover +PASS Margin properties on mover (rtl) +PASS Margin properties on mover (no margin-collapsing) +PASS Margin properties on mpadded +PASS Margin properties on mpadded (rtl) +PASS Margin properties on mpadded (no margin-collapsing) +PASS Margin properties on mphantom +PASS Margin properties on mphantom (rtl) +PASS Margin properties on mphantom (no margin-collapsing) +FAIL Margin properties on mroot assert_true: mroot is supported expected true got false +FAIL Margin properties on mroot (rtl) assert_true: mroot is supported expected true got false +FAIL Margin properties on mroot (no margin-collapsing) assert_true: mroot is supported expected true got false +PASS Margin properties on mrow +PASS Margin properties on mrow (rtl) +PASS Margin properties on mrow (no margin-collapsing) +PASS Margin properties on ms +PASS Margin properties on ms (rtl) +PASS Margin properties on ms (no margin-collapsing) +PASS Margin properties on mspace +FAIL Margin properties on msqrt assert_true: msqrt is supported expected true got false +FAIL Margin properties on msqrt (rtl) assert_true: msqrt is supported expected true got false +FAIL Margin properties on msqrt (no margin-collapsing) assert_true: msqrt is supported expected true got false +PASS Margin properties on mstyle +PASS Margin properties on mstyle (rtl) +PASS Margin properties on mstyle (no margin-collapsing) +PASS Margin properties on msub +PASS Margin properties on msub (rtl) +PASS Margin properties on msub (no margin-collapsing) +PASS Margin properties on msubsup +PASS Margin properties on msubsup (rtl) +PASS Margin properties on msubsup (no margin-collapsing) +PASS Margin properties on msup +PASS Margin properties on msup (rtl) +PASS Margin properties on msup (no margin-collapsing) +PASS Margin properties on mtable +PASS Margin properties on mtable (rtl) +PASS Margin properties on mtable (no margin-collapsing) +PASS Margin properties on mtext +PASS Margin properties on mtext (rtl) +PASS Margin properties on mtext (no margin-collapsing) +PASS Margin properties on munder +PASS Margin properties on munder (rtl) +PASS Margin properties on munder (no margin-collapsing) +PASS Margin properties on munderover +PASS Margin properties on munderover (rtl) +PASS Margin properties on munderover (no margin-collapsing) +PASS Margin properties on semantics +PASS Margin properties on semantics (rtl) +PASS Margin properties on semantics (no margin-collapsing) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003-expected.txt new file mode 100644 index 0000000..005624f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +PASS Margin properties on the children of menclose +PASS Margin properties on the children of merror +PASS Margin properties on the children of mfrac +FAIL Margin properties on the children of mmultiscripts assert_approx_equals: block size expected 345 +/- 1 but got 305 +PASS Margin properties on the children of mover +PASS Margin properties on the children of mpadded +PASS Margin properties on the children of mphantom +FAIL Margin properties on the children of mroot assert_true: mroot is supported expected true got false +PASS Margin properties on the children of mrow +FAIL Margin properties on the children of msqrt assert_true: msqrt is supported expected true got false +PASS Margin properties on the children of mstyle +FAIL Margin properties on the children of msub assert_approx_equals: block size expected 230 +/- 1 but got 210 +FAIL Margin properties on the children of msubsup assert_approx_equals: block size expected 345 +/- 1 but got 305 +FAIL Margin properties on the children of msup assert_approx_equals: block size expected 230 +/- 1 but got 210 +PASS Margin properties on the children of munder +PASS Margin properties on the children of munderover +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003.html new file mode 100644 index 0000000..5f0dbf4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/margin-003.html
@@ -0,0 +1,93 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>margin</title> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms"> +<meta name="assert" content="Verify that margin is taken into account on children."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/feature-detection.js"></script> +<script src="/mathml/support/mathml-fragments.js"></script> +<script src="/mathml/support/layout-comparison.js"></script> +<script> + var epsilon = 1; + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + + for (tag in MathMLFragments) { + if (!FragmentHelper.isValidChildOfMrow(tag) || + FragmentHelper.isEmpty(tag) || + FragmentHelper.isTokenElement(tag) || + tag == "semantics" || + tag == "maction" || + tag == "mtable") + continue; + + test(function() { + assert_true(MathMLFeatureDetection[`has_${tag}`](), `${tag} is supported`); + + document.body.insertAdjacentHTML("beforeend", `<hr/><div>\ +<div style="display: inline-block; border: 1px dashed blue;"><math>${MathMLFragments[tag]}</math></div><br/>\ +<div style="display: inline-block; border: 1px dashed green;"><math>${MathMLFragments[tag]}</math></div>\ +</div>`); + + var div = document.body.lastElementChild; + var elementShrinkWrapContainer = div.firstElementChild; + var element = elementShrinkWrapContainer.firstElementChild.firstElementChild; + var elementContainer = div.firstElementChild; + var referenceShrinkWrapContainer = div.lastElementChild; + var reference = referenceShrinkWrapContainer.firstElementChild.firstElementChild; + + FragmentHelper.forceNonEmptyElement(element); + FragmentHelper.forceNonEmptyElement(reference); + + var mspaceWidth = 20, mspaceHeight = 40, mspaceDepth = 30; + var marginLeft = 10, marginRight = 15, marginTop = 20, marginBottom = 25; + Array.from(element.children).forEach(mrow => { + mrow.outerHTML = `<mspace width="${mspaceWidth}px" height="${mspaceHeight}px" depth='${mspaceDepth}px' style='background: blue; margin-left: ${marginLeft}px; margin-right: ${marginRight}px; margin-top: ${marginTop}px; margin-bottom: ${marginBottom}px;'></mspace>`; + }); + + Array.from(reference.children).forEach(mrow => { + mrow.outerHTML = `<mspace width="${marginLeft+mspaceWidth+marginRight}px" height="${mspaceHeight+marginTop}px" depth='${mspaceDepth+marginBottom}px' style='background: green;'></mspace>`; + }); + + // Compare sizes. + compareSize(element, reference, epsilon); + + // Compare children positions. + var elementBox = element.getBoundingClientRect(); + var referenceBox = reference.getBoundingClientRect(); + for (var i = 0; i < element.children.length; i++) { + var childBox = element.children[i].getBoundingClientRect(); + var referenceChildBox = reference.children[i].getBoundingClientRect(); + assert_approx_equals(childBox.width + marginLeft + marginRight, referenceChildBox.width, epsilon, "inline size (child ${i})"); + assert_approx_equals(childBox.height + marginTop + marginBottom, referenceChildBox.height, epsilon, "block size (child ${i})"); + + assert_approx_equals(childBox.left - marginLeft - elementBox.left, + referenceChildBox.left - referenceBox.left, + epsilon, + `inline position (child ${i})`); + assert_approx_equals(childBox.top - marginTop - elementBox.top, + referenceChildBox.top - referenceBox.top, + epsilon, + `block position (child ${i})`); + } + + // Compare preferred widths. + assert_approx_equals(elementShrinkWrapContainer.offsetWidth, referenceShrinkWrapContainer.offsetWidth, epsilon, "preferred width"); + + }, `Margin properties on the children of ${tag}`); + } + + done(); + } +</script> +</head> +<body> + <div id="log"></div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002-expected.txt new file mode 100644 index 0000000..31be557 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/padding-border-margin/padding-002-expected.txt
@@ -0,0 +1,52 @@ +This is a testharness.js-based test. +PASS Padding properties on maction +PASS Padding properties on maction (rtl) +PASS Padding properties on menclose +PASS Padding properties on menclose (rtl) +PASS Padding properties on merror +PASS Padding properties on merror (rtl) +PASS Padding properties on mfrac +PASS Padding properties on mfrac (rtl) +PASS Padding properties on mi +PASS Padding properties on mi (rtl) +PASS Padding properties on mmultiscripts +PASS Padding properties on mmultiscripts (rtl) +PASS Padding properties on mn +PASS Padding properties on mn (rtl) +PASS Padding properties on mo +PASS Padding properties on mo (rtl) +PASS Padding properties on mover +PASS Padding properties on mover (rtl) +PASS Padding properties on mpadded +PASS Padding properties on mpadded (rtl) +PASS Padding properties on mphantom +PASS Padding properties on mphantom (rtl) +FAIL Padding properties on mroot assert_true: mroot is supported expected true got false +FAIL Padding properties on mroot (rtl) assert_true: mroot is supported expected true got false +PASS Padding properties on mrow +PASS Padding properties on mrow (rtl) +PASS Padding properties on ms +PASS Padding properties on ms (rtl) +PASS Padding properties on mspace +FAIL Padding properties on msqrt assert_true: msqrt is supported expected true got false +FAIL Padding properties on msqrt (rtl) assert_true: msqrt is supported expected true got false +PASS Padding properties on mstyle +PASS Padding properties on mstyle (rtl) +PASS Padding properties on msub +PASS Padding properties on msub (rtl) +PASS Padding properties on msubsup +PASS Padding properties on msubsup (rtl) +PASS Padding properties on msup +PASS Padding properties on msup (rtl) +PASS Padding properties on mtable +PASS Padding properties on mtable (rtl) +PASS Padding properties on mtext +PASS Padding properties on mtext (rtl) +PASS Padding properties on munder +PASS Padding properties on munder (rtl) +PASS Padding properties on munderover +PASS Padding properties on munderover (rtl) +PASS Padding properties on semantics +PASS Padding properties on semantics (rtl) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/mathml/support/mathml-fragments.js b/third_party/blink/web_tests/external/wpt/mathml/support/mathml-fragments.js index 8376ccf..7e2113e 100644 --- a/third_party/blink/web_tests/external/wpt/mathml/support/mathml-fragments.js +++ b/third_party/blink/web_tests/external/wpt/mathml/support/mathml-fragments.js
@@ -132,6 +132,14 @@ tag == "mtd"); }, + isTokenElement: function(tag) { + return (tag == "mi" || + tag == "mtext" || + tag == "mo" || + tag == "mn" || + tag == "ms") + }, + isEmpty: function(tag) { return tag === "mspace" || tag == "mprescripts" || tag == "none"; },
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt index 42484619..9b071f9 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. PASS global setup -FAIL FetchEvent.handled should resolve when respondWith() is not called assert_equals: expected "RESOLVED" but got "FAILED" +FAIL FetchEvent.handled should resolve when respondWith() is not called for a navigation request assert_equals: expected "RESOLVED" but got "FAILED" +FAIL FetchEvent.handled should resolve when respondWith() is not called for a sub-resource request assert_equals: expected "RESOLVED" but got "FAILED" FAIL FetchEvent.handled should reject when respondWith() is not called and the event is canceled assert_equals: expected "REJECTED" but got "FAILED" FAIL FetchEvent.handled should resolve when the promise provided to respondWith() is resolved assert_equals: expected "RESOLVED" but got "FAILED" FAIL FetchEvent.handled should reject when the promise provided to respondWith() is resolved to an invalid response assert_equals: expected "REJECTED" but got "FAILED"
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html index 2d6f6c86..89f3d79a 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/fetch-event-handled.https.html
@@ -30,14 +30,21 @@ await service_worker_unregister_and_register(t, script, scope); worker = registration.installing; await wait_for_state(t, worker, 'activated'); - frame = await with_iframe(scope); }, 'global setup'); promise_test(async (t) => { + frame = await with_iframe(scope); + const message = await wait_for_message_from_worker(); + assert_equals(message, 'RESOLVED'); +}, 'FetchEvent.handled should resolve when respondWith() is not called for a' + + ' navigation request'); + +promise_test(async (t) => { frame.contentWindow.fetch('dummy.txt?respondWith-not-called'); const message = await wait_for_message_from_worker(); assert_equals(message, 'RESOLVED'); -}, 'FetchEvent.handled should resolve when respondWith() is not called'); +}, 'FetchEvent.handled should resolve when respondWith() is not called for a' + + ' sub-resource request'); promise_test(async (t) => { frame.contentWindow.fetch(
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js index 4af58e2..0dc6de0 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/fetch-event-handled-worker.js
@@ -9,7 +9,9 @@ } self.addEventListener('fetch', function(event) { - const clientId = event.clientId; + const clientId = (event.request.mode === 'navigate') ? + event.resultingClientId : event.clientId; + try { event.handled.then(() => { send_message_to_client('RESOLVED', clientId);
diff --git a/third_party/blink/web_tests/external/wpt/svg/animations/svglength-additive-by-8.html b/third_party/blink/web_tests/external/wpt/svg/animations/svglength-additive-by-8.html index c61cb65..459fc73 100644 --- a/third_party/blink/web_tests/external/wpt/svg/animations/svglength-additive-by-8.html +++ b/third_party/blink/web_tests/external/wpt/svg/animations/svglength-additive-by-8.html
@@ -13,8 +13,8 @@ <!-- an1: Change width from 10 to 50 in 4s --> <!-- an2: Change width from 10 to 100 in 4s starting at 5s --> <rect width="10" height="100" fill="green"> - <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="calc(4% + 8)" begin="0s" dur="4s"/> - <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="calc(10% + 10)" begin="5s" dur="4s"/> + <animate id="an1" attributeType="XML" attributeName="width" fill="remove" by="calc(4% + 8px)" begin="0s" dur="4s"/> + <animate id="an2" attributeType="XML" attributeName="width" additive="replace" fill="freeze" by="calc(10% + 10px)" begin="5s" dur="4s"/> </rect> </svg> @@ -73,4 +73,4 @@ window.animationStartsImmediately = true; -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-invalid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-invalid.svg index 0c356b6..53a9640c 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-invalid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-invalid.svg
@@ -17,6 +17,9 @@ test_invalid_value("stroke-dasharray", "none 10px"); test_invalid_value("stroke-dasharray", "20px / 30px"); test_invalid_value("stroke-dasharray", "-40px"); +test_invalid_value("stroke-dasharray", "calc(2px + 3)"); +test_invalid_value("stroke-dasharray", "calc(10% + 5)"); +test_invalid_value("stroke-dasharray", "calc(40 + calc(3px + 6%))"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-valid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-valid.svg index e47ebc62..9326118c 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-valid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dasharray-valid.svg
@@ -23,6 +23,9 @@ test_valid_value("stroke-dasharray", "10pt 20% 30pc 40in", "10pt, 20%, 30pc, 40in"); test_valid_value("stroke-dasharray", "10vmin, 20vmax, 30em, 40ex"); test_valid_value("stroke-dasharray", "0, 5", ["0, 5", "0px, 5px"]); // Edge/Safari serialize numbers as lengths. +test_valid_value("stroke-dasharray", "calc(3)"); +test_valid_value("stroke-dasharray", "calc(2 + 1)", "calc(3)"); +test_valid_value("stroke-dasharray", "calc(2 + (7 - 5))", "calc(4)"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-invalid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-invalid.svg index 64e2eec7..2040355 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-invalid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-invalid.svg
@@ -17,6 +17,9 @@ test_invalid_value("stroke-dashoffset", "-10.px"); test_invalid_value("stroke-dashoffset", "30deg"); test_invalid_value("stroke-dashoffset", "40px 50%"); +test_invalid_value("stroke-dashoffset", "calc(2px + 3)"); +test_invalid_value("stroke-dashoffset", "calc(10% + 5)"); +test_invalid_value("stroke-dashoffset", "calc(40 + calc(3px + 6%))"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid-expected.txt b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid-expected.txt index a683e2f..2de3aab 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid-expected.txt
@@ -5,5 +5,8 @@ FAIL e.style['stroke-dashoffset'] = "30" should set the property value assert_equals: serialization should be canonical expected "30px" but got "30" PASS e.style['stroke-dashoffset'] = "40Q" should set the property value PASS e.style['stroke-dashoffset'] = "calc(2em + 3ex)" should set the property value +PASS e.style['stroke-dashoffset'] = "calc(3)" should set the property value +PASS e.style['stroke-dashoffset'] = "calc(2 + 1)" should set the property value +PASS e.style['stroke-dashoffset'] = "calc(2 + (7 - 5))" should set the property value Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid.svg index f34774e..fe7ba12c 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-dashoffset-valid.svg
@@ -19,6 +19,9 @@ test_valid_value("stroke-dashoffset", "30", "30px"); test_valid_value("stroke-dashoffset", "40Q", "40q"); test_valid_value("stroke-dashoffset", "calc(2em + 3ex)"); +test_valid_value("stroke-dashoffset", "calc(3)"); +test_valid_value("stroke-dashoffset", "calc(2 + 1)", "calc(3)"); +test_valid_value("stroke-dashoffset", "calc(2 + (7 - 5))", "calc(4)"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-invalid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-invalid.svg index 0d3f63d..2111e37 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-invalid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-invalid.svg
@@ -17,6 +17,9 @@ test_invalid_value("stroke-width", "10px 20px"); test_invalid_value("stroke-width", "-1px"); test_invalid_value("stroke-width", "-10%"); +test_invalid_value("stroke-width", "calc(2px + 3)"); +test_invalid_value("stroke-width", "calc(10% + 5)"); +test_invalid_value("stroke-width", "calc(40 + calc(3px + 6%))"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid-expected.txt b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid-expected.txt index 9ec8028..e9b028d 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid-expected.txt
@@ -6,5 +6,8 @@ PASS e.style['stroke-width'] = "4%" should set the property value PASS e.style['stroke-width'] = "5vmin" should set the property value PASS e.style['stroke-width'] = "calc(50% + 60px)" should set the property value +PASS e.style['stroke-width'] = "calc(3)" should set the property value +PASS e.style['stroke-width'] = "calc(2 + 1)" should set the property value +PASS e.style['stroke-width'] = "calc(2 + (7 - 5))" should set the property value Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid.svg b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid.svg index f9078128..1ee0449 100644 --- a/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid.svg +++ b/third_party/blink/web_tests/external/wpt/svg/painting/parsing/stroke-width-valid.svg
@@ -20,6 +20,9 @@ test_valid_value("stroke-width", "4%"); test_valid_value("stroke-width", "5vmin"); test_valid_value("stroke-width", "calc(50% + 60px)"); +test_valid_value("stroke-width", "calc(3)"); +test_valid_value("stroke-width", "calc(2 + 1)", "calc(3)"); +test_valid_value("stroke-width", "calc(2 + (7 - 5))", "calc(4)"); ]]></script> </svg>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/simulcast/.eslintignore b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/.eslintignore new file mode 100644 index 0000000..90fee69 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/.eslintignore
@@ -0,0 +1 @@ +sdp/
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/simulcast/basic.https.html b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/basic.https.html new file mode 100644 index 0000000..ae2e7ee --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/basic.https.html
@@ -0,0 +1,56 @@ +<!doctype html> +<meta charset=utf-8> +<title>RTCPeerConnection Simulcast Tests</title> +<script src="../third_party/sdp/sdp.js"></script> +<script src="simulcast.js"></script> +<script src="../RTCPeerConnection-helper.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + const rids = [0, 1, 2]; + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection(); + t.add_cleanup(() => pc2.close()); + + exchangeIceCandidates(pc1, pc2); + + const metadataToBeLoaded = []; + pc2.ontrack = (e) => { + const stream = e.streams[0]; + const v = document.createElement('video'); + v.autoplay = true; + v.srcObject = stream; + v.id = stream.id + metadataToBeLoaded.push(new Promise((resolve) => { + v.addEventListener('loadedmetadata', () => { + resolve(); + }); + })); + }; + + // use getUserMedia as getNoiseStream does not have enough entropy to ramp-up. + const stream = await navigator.mediaDevices.getUserMedia({video: {width: 1280, height: 720}}); + t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); + pc1.addTransceiver(stream.getVideoTracks()[0], { + streams: [stream], + sendEncodings: rids.map(rid => {rid}), + }); + + const offer = await pc1.createOffer(); + await pc1.setLocalDescription(offer), + await pc2.setRemoteDescription({ + type: 'offer', + sdp: swapRidAndMidExtensionsInSimulcastOffer(offer, rids), + }); + const answer = await pc2.createAnswer(); + await pc2.setLocalDescription(answer); + await pc1.setRemoteDescription({ + type: 'answer', + sdp: swapRidAndMidExtensionsInSimulcastAnswer(answer, pc1.localDescription, rids), + }); + assert_equals(metadataToBeLoaded.length, 3); + return Promise.all(metadataToBeLoaded); +}, 'Basic simulcast setup with three spatial layers'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/simulcast/simulcast.js b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/simulcast.js new file mode 100644 index 0000000..ed08ddc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webrtc/simulcast/simulcast.js
@@ -0,0 +1,77 @@ +'use strict'; +/* Helper functions to munge SDP and split the sending track into + * separate tracks on the receiving end. This can be done in a number + * of ways, the one used here uses the fact that the MID and RID header + * extensions which are used for packet routing share the same wire + * format. The receiver interprets the rids from the sender as mids + * which allows receiving the different spatial resolutions on separate + * m-lines and tracks. + */ +const extensionsToFilter = [ + 'urn:ietf:params:rtp-hdrext:sdes:mid', + 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + 'urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id', +]; + +function swapRidAndMidExtensionsInSimulcastOffer(offer, rids) { + const sections = SDPUtils.splitSections(offer.sdp); + const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); + const ice = SDPUtils.getIceParameters(sections[1], sections[0]); + const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); + + // The gist of this hack is that rid and mid have the same wire format. + const rid = rtpParameters.headerExtensions.find(ext => ext.uri === 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'); + rtpParameters.headerExtensions = rtpParameters.headerExtensions.filter(ext => { + return !extensionsToFilter.includes(ext.uri); + }); + // This tells the other side that the RID packets are actually mids. + rtpParameters.headerExtensions.push({id: rid.id, uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', direction: 'sendrecv'}); + + // Filter rtx as we have no way to (re)interpret rrid. + // Not doing this makes probing use RTX, it's not understood and ramp-up is slower. + rtpParameters.codecs = rtpParameters.codecs.filter(c => c.name.toUpperCase() !== 'RTX'); + + let sdp = SDPUtils.writeSessionBoilerplate() + + SDPUtils.writeDtlsParameters(dtls, 'actpass') + + SDPUtils.writeIceParameters(ice) + + 'a=group:BUNDLE ' + rids.join(' ') + '\r\n'; + const baseRtpDescription = SDPUtils.writeRtpDescription('video', rtpParameters); + rids.forEach(rid => { + sdp += baseRtpDescription + + 'a=mid:' + rid + '\r\n' + + 'a=msid:rid-' + rid + ' rid-' + rid + '\r\n'; + }); + return sdp; +} + +function swapRidAndMidExtensionsInSimulcastAnswer(answer, localDescription, rids) { + const sections = SDPUtils.splitSections(answer.sdp); + const dtls = SDPUtils.getDtlsParameters(sections[1], sections[0]); + const ice = SDPUtils.getIceParameters(sections[1], sections[0]); + const rtpParameters = SDPUtils.parseRtpParameters(sections[1]); + + rtpParameters.headerExtensions = rtpParameters.headerExtensions.filter(ext => { + return !extensionsToFilter.includes(ext.uri); + }); + const localMid = SDPUtils.getMid(SDPUtils.splitSections(localDescription.sdp)[1]); + let sdp = SDPUtils.writeSessionBoilerplate() + + SDPUtils.writeDtlsParameters(dtls, 'active') + + SDPUtils.writeIceParameters(ice) + + 'a=group:BUNDLE ' + localMid + '\r\n'; + sdp += SDPUtils.writeRtpDescription('video', rtpParameters); + sdp += 'a=mid:' + localMid + '\r\n'; + + rids.forEach(rid => { + sdp += 'a=rid:' + rid + ' recv\r\n'; + }); + sdp += 'a=simulcast:recv ' + rids.join(';') + '\r\n'; + + // Re-add headerextensions we filtered. + const headerExtensions = SDPUtils.parseRtpParameters(SDPUtils.splitSections(localDescription.sdp)[1]).headerExtensions; + headerExtensions.forEach(ext => { + if (extensionsToFilter.includes(ext.uri)) { + sdp += 'a=extmap:' + ext.id + ' ' + ext.uri + '\r\n'; + } + }); + return sdp; +}
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt index 82851a25..f945b4f 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -webkit-app-region: none --webkit-appearance: none -webkit-border-horizontal-spacing: 0px -webkit-border-image: none -webkit-border-vertical-spacing: 0px @@ -63,6 +62,7 @@ animation-name: none animation-play-state: running animation-timing-function: ease +appearance: none backdrop-filter: none backface-visibility: visible background-attachment: scroll
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt index e814287..14ef84b5 100644 --- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt +++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -webkit-app-region: none --webkit-appearance: none -webkit-border-horizontal-spacing: 0px -webkit-border-image: none -webkit-border-vertical-spacing: 0px @@ -63,6 +62,7 @@ animation-name: none animation-play-state: running animation-timing-function: ease +appearance: none backdrop-filter: none backface-visibility: visible background-attachment: scroll
diff --git a/third_party/blink/web_tests/payments/payment-request-interface.html b/third_party/blink/web_tests/payments/payment-request-interface.html index 556ec028..d3fcae0c 100644 --- a/third_party/blink/web_tests/payments/payment-request-interface.html +++ b/third_party/blink/web_tests/payments/payment-request-interface.html
@@ -273,84 +273,84 @@ return promise_rejects_dom(t, 'InvalidStateError', new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails()).abort()); }, 'abort() without show() should reject with error'); -generate_tests(assert_throws, [ - ['PaymentRequest constructor should throw for incorrect parameter types.', new TypeError(), function() { +generate_tests(assert_throws_js, [ + ['PaymentRequest constructor should throw for incorrect parameter types.', TypeError, function() { new PaymentRequest('', '', '') }], - ['PaymentRequest constructor should throw for undefined required parameters.', new TypeError(), function() { + ['PaymentRequest constructor should throw for undefined required parameters.', TypeError, function() { new PaymentRequest(undefined, undefined) }], - ['PaymentRequest constructor should throw for null required parameter.', new TypeError(), function() { + ['PaymentRequest constructor should throw for null required parameter.', TypeError, function() { new PaymentRequest(null, null) }], - ['Empty list of supported payment method identifiers should throw TypeError.', new TypeError(), function() { + ['Empty list of supported payment method identifiers should throw TypeError.', TypeError, function() { new PaymentRequest([], buildDetails()) }], - ['Empty supported payment method identifier should throw RangeError.', new RangeError(), function() { + ['Empty supported payment method identifier should throw RangeError.', RangeError, function() { new PaymentRequest([{'supportedMethods': ''}], buildDetails()) }], - ['Absence of total should throw TypeError.', new TypeError(), function() { + ['Absence of total should throw TypeError.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'displayItems': [buildItem()]}) }], - ['Negative total value should throw a TypeError.', new TypeError(), function() { + ['Negative total value should throw a TypeError.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails('total', {'value': '-0.01'})) }], - ['Negative total value in PaymentDetailsModifier should throw a TypeError.', new TypeError(), function() { + ['Negative total value in PaymentDetailsModifier should throw a TypeError.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'modifiers': [{'supportedMethods': 'foo', 'total': buildItem({'value': '-0.01'})}]}) }], - ['Undefined supportedMethods in modifiers should throw TypeError.', new TypeError(), function() { + ['Undefined supportedMethods in modifiers should throw TypeError.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'modifiers': [{'supportedMethods': undefined}]}) }], - ['Empty supportedMethods in modifiers should throw RangeError.', new RangeError(), function() { + ['Empty supportedMethods in modifiers should throw RangeError.', RangeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'modifiers': [{'supportedMethods': ''}]}) }], - ['Absence of supportedMethods in modifiers should throw TypeError.', new TypeError(), function() { + ['Absence of supportedMethods in modifiers should throw TypeError.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'modifiers': [{'total': buildItem()}]}) }], - ['Empty details should throw', new TypeError(), function() { + ['Empty details should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {}) }], - ['Null items should throw', new TypeError(), function() { + ['Null items should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'displayItems': null}); }], - ['Null shipping options should throw', new TypeError(), function() { + ['Null shipping options should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo'}], {'total': buildItem(), 'displayItems': [buildItem()], 'shippingOptions': null}); }], - ['Undefined PaymentShippingType value for shppingType should throw a TypeError', new TypeError(), function() { + ['Undefined PaymentShippingType value for shppingType should throw a TypeError', TypeError, function() { var request = new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails(), {'requestShipping': true, 'shippingType': 'invalid'}); }], - ['Null for shppingType should throw a TypeError', new TypeError(), function() { + ['Null for shppingType should throw a TypeError', TypeError, function() { var request = new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails(), {'requestShipping': true, 'shippingType': null}); }], - ['Array value for shppingType should throw a TypeError', new TypeError(), function() { + ['Array value for shppingType should throw a TypeError', TypeError, function() { var request = new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails(), {'requestShipping': true, 'shippingType': []}); }], - ['Object value for shppingType should throw a TypeError', new TypeError(), function() { + ['Object value for shppingType should throw a TypeError', TypeError, function() { var request = new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails(), {'requestShipping': true, 'shippingType': {}}); }], - ['Numeric value for shppingType should throw a TypeError', new TypeError(), function() { + ['Numeric value for shppingType should throw a TypeError', TypeError, function() { var request = new PaymentRequest([{'supportedMethods': 'foo'}], buildDetails(), {'requestShipping': true, 'shippingType': 0}); }], // Payment method specific data should be a JSON-serializable object. - ['String value for payment method specific data parameter should throw', new TypeError(), function() { + ['String value for payment method specific data parameter should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo', 'data': 'foo'}], buildDetails(), {}) }], - ['Numeric value for payment method specific data parameter should throw', new TypeError(), function() { + ['Numeric value for payment method specific data parameter should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo', 'data': 42}], buildDetails(), {}) }], - ['Infinite JSON value for one of the payment method specific data pieces should throw', new TypeError(), function() { + ['Infinite JSON value for one of the payment method specific data pieces should throw', TypeError, function() { var infiniteData = {'foo': {}}; infiniteData.foo = infiniteData; new PaymentRequest([{'supportedMethods': 'foo', 'data': infiniteData}], buildDetails()) }], - ['Null for payment method specific data parameter should throw', new TypeError(), function() { + ['Null for payment method specific data parameter should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo', 'data': null}], buildDetails()) }], - ['Empty string for payment method specific data parameter should throw', new TypeError(), function() { + ['Empty string for payment method specific data parameter should throw', TypeError, function() { new PaymentRequest([{'supportedMethods': 'foo', 'data': ''}], buildDetails()) }], - ['PaymentRequest constructor should throw for invalid "basic-card" parameters.', new TypeError(), function() { + ['PaymentRequest constructor should throw for invalid "basic-card" parameters.', TypeError, function() { new PaymentRequest([{'supportedMethods': 'basic-card', 'data': {'supportedTypes': 0, 'supportedNetworks': 'foo'}}], buildDetails()) }] ]);
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/origin/assorted.window-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/origin/assorted.window-expected.txt new file mode 100644 index 0000000..5f71302 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/fetch/origin/assorted.window-expected.txt
@@ -0,0 +1,49 @@ +Content-Type: text/plain +This is a testharness.js-based test. +PASS Origin header and 308 redirect +PASS Origin header and GET navigation +PASS Origin header and POST navigation +PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer +FAIL Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +FAIL Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer +FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and POST same-origin navigation with Referrer-Policy same-origin +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy same-origin +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and POST cross-origin navigation with Referrer-Policy same-origin +FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy same-origin assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and POST same-origin navigation with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin navigation with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin navigation with Referrer-Policy unsafe-url +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin navigation with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy unsafe-url +Harness: the test ran to completion. + +#EOF +#EOF
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt b/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt index a45b3538..2ca0d7c 100644 --- a/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt +++ b/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt
@@ -1,6 +1,6 @@ This is a testharness.js-based test. PASS Continuations across a block -20 -FAIL Continuations across a block -15 resources/testharness.js:2024:25) +FAIL Continuations across a block -15 resources/testharness.js:1867:25) expected <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>|BBBBB</p>, but got <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>BB|BBB</p>, sameupto <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>
diff --git a/third_party/blink/web_tests/resources/idlharness.js b/third_party/blink/web_tests/resources/idlharness.js index a430a34b..18b11ec 100644 --- a/third_party/blink/web_tests/resources/idlharness.js +++ b/third_party/blink/web_tests/resources/idlharness.js
@@ -84,16 +84,33 @@ .reduce(function(m, n) { return Math.min(m, n); }); } +// A helper to get the global of a Function object. This is needed to determine +// which global exceptions the function throws will come from. +function globalOf(func) +{ + try { + // Use the fact that .constructor for a Function object is normally the + // Function constructor, which can be used to mint a new function in the + // right global. + return func.constructor("return this;")(); + } catch (e) { + } + // If the above fails, because someone gave us a non-function, or a function + // with a weird proto chain or weird .constructor property, just fall back + // to 'self'. + return self; +} + function throwOrReject(a_test, operation, fn, obj, args, message, cb) { if (operation.idlType.generic !== "Promise") { - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(fn).TypeError, function() { fn.apply(obj, args); }, message); cb(); } else { try { - promise_rejects(a_test, new TypeError(), fn.apply(obj, args), message).then(cb, cb); + promise_rejects_js(a_test, TypeError, fn.apply(obj, args), message).then(cb, cb); } catch (e){ a_test.step(function() { assert_unreached("Throws \"" + e + "\" instead of rejecting promise"); @@ -193,6 +210,12 @@ this["implements"] = {}; this["includes"] = {}; this["inheritance"] = {}; + + /** + * Record of skipped IDL items, in case we later realize that they are a + * dependency (to retroactively process them). + */ + this.skipped = new Map(); }; IdlArray.prototype.add_idls = function(raw_idls, options) @@ -230,7 +253,11 @@ IdlArray.prototype.add_dependency_idls = function(raw_idls, options) { - const parsed_idls = WebIDL2.parse(raw_idls); + return this.internal_add_dependency_idls(WebIDL2.parse(raw_idls), options); +}; + +IdlArray.prototype.internal_add_dependency_idls = function(parsed_idls, options) +{ const new_options = { only: [] } const all_deps = new Set(); @@ -244,22 +271,50 @@ all_deps.add(k); this.includes[k].forEach(v => all_deps.add(v)); }); - this.partials.map(p => p.name).forEach(v => all_deps.add(v)); - // Add the attribute idlTypes of all the nested members of all tested idls. - for (const obj of [this.members, this.partials]) { - const tested = Object.values(obj).filter(m => !m.untested && m.members); - for (const parsed of tested) { - for (const attr of Object.values(parsed.members).filter(m => !m.untested && m.type === 'attribute')) { - all_deps.add(attr.idlType.idlType); - } + this.partials.forEach(p => all_deps.add(p.name)); + // Add 'TypeOfType' for each "typedef TypeOfType MyType;" entry. + Object.entries(this.members).forEach(([k, v]) => { + if (v instanceof IdlTypedef) { + let defs = v.idlType.union + ? v.idlType.idlType.map(t => t.idlType) + : [v.idlType.idlType]; + defs.forEach(d => all_deps.add(d)); } - } + }); + + // Add the attribute idlTypes of all the nested members of idls. + const attrDeps = parsedIdls => { + return parsedIdls.reduce((deps, parsed) => { + if (parsed.members) { + for (const attr of Object.values(parsed.members).filter(m => m.type === 'attribute')) { + let attrType = attr.idlType; + // Check for generic members (e.g. FrozenArray<MyType>) + if (attrType.generic) { + deps.add(attrType.generic); + attrType = attrType.idlType; + } + deps.add(attrType.idlType); + } + } + if (parsed.base in this.members) { + attrDeps([this.members[parsed.base]]).forEach(dep => deps.add(dep)); + } + return deps; + }, new Set()); + }; + + const testedMembers = Object.values(this.members).filter(m => !m.untested && m.members); + attrDeps(testedMembers).forEach(dep => all_deps.add(dep)); + + const testedPartials = this.partials.filter(m => !m.untested && m.members); + attrDeps(testedPartials).forEach(dep => all_deps.add(dep)); + if (options && options.except && options.only) { throw new IdlHarnessError("The only and except options can't be used together."); } - const should_skip = name => { + const defined_or_untested = name => { // NOTE: Deps are untested, so we're lenient, and skip re-encountered definitions. // e.g. for 'idl' containing A:B, B:C, C:D // array.add_idls(idl, {only: ['A','B']}). @@ -268,9 +323,7 @@ return name in this.members || this.is_excluded_by_options(name, options); } - // Record of skipped items, in case we later determine they are a dependency. // Maps name -> [parsed_idl, ...] - const skipped = new Map(); const process = function(parsed) { var deps = []; if (parsed.name) { @@ -284,13 +337,15 @@ } deps = deps.filter(function(name) { - if (!name || should_skip(name) || !all_deps.has(name)) { + if (!name + || name === parsed.name && defined_or_untested(name) + || !all_deps.has(name)) { // Flag as skipped, if it's not already processed, so we can // come back to it later if we retrospectively call it a dep. if (name && !(name in this.members)) { - skipped.has(name) - ? skipped.get(name).push(parsed) - : skipped.set(name, [parsed]); + this.skipped.has(name) + ? this.skipped.get(name).push(parsed) + : this.skipped.set(name, [parsed]); } return false; } @@ -328,9 +383,9 @@ } for (const deferred of follow_up) { - if (skipped.has(deferred)) { - const next = skipped.get(deferred); - skipped.delete(deferred); + if (this.skipped.has(deferred)) { + const next = this.skipped.get(deferred); + this.skipped.delete(deferred); next.forEach(process); } } @@ -463,8 +518,7 @@ break; case "callback": - // TODO - console.log("callback not yet supported"); + this.members[parsed_idl.name] = new IdlCallback(parsed_idl); break; case "enum": @@ -586,7 +640,7 @@ // sequence types if (type.generic == "sequence" || type.generic == "FrozenArray") { - return this.is_json_type(idlType); + return this.is_json_type(idlType[0]); } if (typeof idlType != "string") { throw new Error("Unexpected type " + JSON.stringify(idlType)); } @@ -694,11 +748,11 @@ result = new Set(result); } if (exposed && exposed.length) { - var set = exposed[0].rhs.value; + const { rhs } = exposed[0]; // Could be a list or a string. - if (typeof set == "string") { - set = [ set ]; - } + const set = rhs.type === "identifier-list" ? + rhs.value.map(id => id.value) : + [ rhs.value ]; result = new Set(set); } if (result && result.has("Worker")) { @@ -771,10 +825,20 @@ if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface."; if (!(rhs in this.members)) throw errStr + rhs + " is undefined."; if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface."; - this.members[rhs].members.forEach(function(member) - { - this.members[lhs].members.push(new IdlInterfaceMember(member)); - }.bind(this)); + + if (this.members[rhs].members.length) { + test(function () { + var clash = this.members[rhs].members.find(function(member) { + return this.members[lhs].members.find(function(m) { + return this.are_duplicate_members(m, member); + }.bind(this)); + }.bind(this)); + this.members[rhs].members.forEach(function(member) { + this.members[lhs].members.push(new IdlInterfaceMember(member)); + }.bind(this)); + assert_true(!clash, "member " + (clash && clash.name) + " is unique"); + }.bind(this), lhs + " implements " + rhs + ": member names are unique"); + } }.bind(this)); } this["implements"] = {}; @@ -788,10 +852,23 @@ if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface."; if (!(rhs in this.members)) throw errStr + rhs + " is undefined."; if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface."; - this.members[rhs].members.forEach(function(member) - { - this.members[lhs].members.push(new IdlInterfaceMember(member)); - }.bind(this)); + + if (this.members[rhs].members.length) { + test(function () { + var clash = this.members[rhs].members.find(function(member) { + return this.members[lhs].members.find(function(m) { + return this.are_duplicate_members(m, member); + }.bind(this)); + }.bind(this)); + this.members[rhs].members.forEach(function(member) { + assert_true( + this.members[lhs].members.every(m => !this.are_duplicate_members(m, member)), + "member " + member.name + " is unique"); + this.members[lhs].members.push(new IdlInterfaceMember(member)); + }.bind(this)); + assert_true(!clash, "member " + (clash && clash.name) + " is unique"); + }.bind(this), lhs + " includes " + rhs + ": member names are unique"); + } }.bind(this)); } this["includes"] = {}; @@ -853,24 +930,27 @@ || this.members[parsed_idl.name] instanceof IdlDictionary || this.members[parsed_idl.name] instanceof IdlNamespace); + // Ensure unique test name in case of multiple partials. let partialTestName = parsed_idl.name; - if (!parsed_idl.untested) { - // Ensure unique test name in case of multiple partials. - let partialTestCount = 1; - if (testedPartials.has(parsed_idl.name)) { - partialTestCount += testedPartials.get(parsed_idl.name); - partialTestName = `${partialTestName}[${partialTestCount}]`; - } - testedPartials.set(parsed_idl.name, partialTestCount); + let partialTestCount = 1; + if (testedPartials.has(parsed_idl.name)) { + partialTestCount += testedPartials.get(parsed_idl.name); + partialTestName = `${partialTestName}[${partialTestCount}]`; + } + testedPartials.set(parsed_idl.name, partialTestCount); + if (!parsed_idl.untested) { test(function () { assert_true(originalExists, `Original ${parsed_idl.type} should be defined`); - var expected = IdlInterface; + var expected; switch (parsed_idl.type) { - case 'interface': expected = IdlInterface; break; case 'dictionary': expected = IdlDictionary; break; case 'namespace': expected = IdlNamespace; break; + case 'interface': + case 'interface mixin': + default: + expected = IdlInterface; break; } assert_true( expected.prototype.isPrototypeOf(this.members[parsed_idl.name]), @@ -916,14 +996,36 @@ this.members[parsed_idl.name].extAttrs.push(extAttr); }.bind(this)); } - parsed_idl.members.forEach(function(member) - { - this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member)); - }.bind(this)); + if (parsed_idl.members.length) { + test(function () { + var clash = parsed_idl.members.find(function(member) { + return this.members[parsed_idl.name].members.find(function(m) { + return this.are_duplicate_members(m, member); + }.bind(this)); + }.bind(this)); + parsed_idl.members.forEach(function(member) + { + this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member)); + }.bind(this)); + assert_true(!clash, "member " + (clash && clash.name) + " is unique"); + }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: member names are unique`); + } }.bind(this)); this.partials = []; } +IdlArray.prototype.are_duplicate_members = function(m1, m2) { + if (m1.name !== m2.name) { + return false; + } + if (m1.type === 'operation' && m2.type === 'operation' + && m1.arguments.length !== m2.arguments.length) { + // Method overload. TODO: Deep comparison of arguments. + return false; + } + return true; +} + IdlArray.prototype.assert_type_is = function(value, type) { if (type.idlType in this.members @@ -984,7 +1086,7 @@ // Nothing we can do. return; } - this.assert_type_is(value[0], type.idlType); + this.assert_type_is(value[0], type.idlType[0]); return; } @@ -1004,11 +1106,11 @@ // Nothing we can do. return; } - this.assert_type_is(value[0], type.idlType); + this.assert_type_is(value[0], type.idlType[0]); return; } - type = type.idlType; + type = Array.isArray(type.idlType) ? type.idlType[0] : type.idlType; switch(type) { @@ -1105,6 +1207,10 @@ assert_regexp_match(value, /^([\x00-\ud7ff\ue000-\uffff]|[\ud800-\udbff][\udc00-\udfff])*$/); return; + case "DataView": + assert_equals(typeof value, "DataView"); + return; + case "object": assert_in_array(typeof value, ["object", "function"], "wrong type: not object or function"); return; @@ -1138,9 +1244,13 @@ { // TODO: Test when we actually have something to test this on } + else if (this.members[type] instanceof IdlCallback) + { + assert_equals(typeof value, "function"); + } else { - throw new IdlHarnessError("Type " + type + " isn't an interface or dictionary"); + throw new IdlHarnessError("Type " + type + " isn't an interface, callback or dictionary"); } }; @@ -1225,7 +1335,7 @@ this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); }); if (this.has_extended_attribute("Unforgeable")) { this.members - .filter(function(m) { return !m["static"] && (m.type == "attribute" || m.type == "operation"); }) + .filter(function(m) { return m.special !== "static" && (m.type == "attribute" || m.type == "operation"); }) .forEach(function(m) { return m.isUnforgeable = true; }); } @@ -1376,7 +1486,7 @@ if (I.has_default_to_json_regular_operation()) { isDefault = true; I.members.forEach(function(m) { - if (!m.static && m.type == "attribute" && I.array.is_json_type(m.idlType)) { + if (m.special !== "static" && m.type == "attribute" && I.array.is_json_type(m.idlType)) { map.set(m.name, m.idlType); } }); @@ -1470,6 +1580,17 @@ this.test_members(); }; +// This supports both Constructor extended attributes and constructor +// operations until all idl fragments have been updated. +IdlInterface.prototype.constructors = function() +{ + var extendedAttributes = this.extAttrs + .filter(function(attr) { return attr.name == "Constructor"; }); + var operations = this.members + .filter(function(m) { return m.type == "constructor"; }); + return extendedAttributes.concat(operations); +} + IdlInterface.prototype.test_self = function() { subsetTestByKey(this.name, test, function() @@ -1557,17 +1678,17 @@ "prototype of self's property " + format_value(this.name) + " is not Function.prototype"); } - if (!this.has_extended_attribute("Constructor")) { + if (!this.constructors().length) { // "The internal [[Call]] method of the interface object behaves as // follows . . . // // "If I was not declared with a [Constructor] extended attribute, // then throw a TypeError." var interface_object = this.get_interface_object(); - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(interface_object).TypeError, function() { interface_object(); }, "interface object didn't throw TypeError when called as a function"); - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(interface_object).TypeError, function() { new interface_object(); }, "interface object didn't throw TypeError when called as a constructor"); } @@ -1592,8 +1713,7 @@ assert_false(desc.enumerable, this.name + ".length should not be enumerable"); assert_true(desc.configurable, this.name + ".length should be configurable"); - var constructors = this.extAttrs - .filter(function(attr) { return attr.name == "Constructor"; }); + var constructors = this.constructors(); var expected_length = minOverloadLength(constructors); assert_equals(this.get_interface_object().length, expected_length, "wrong value for " + this.name + ".length"); }.bind(this), this.name + " interface object length"); @@ -1647,7 +1767,7 @@ } var aliases; if (rhs.type === "identifier-list") { - aliases = rhs.value; + aliases = rhs.value.map(id => id.value); } else { // rhs.type === identifier aliases = [ rhs.value ]; } @@ -1785,7 +1905,7 @@ var args = constructor.arguments.map(function(arg) { return create_suitable_object(arg.idlType); }); - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(self[name]).TypeError, function() { self[name](...args); }.bind(this)); }.bind(this), this.name + " interface: named constructor without 'new'"); @@ -2048,7 +2168,7 @@ var newValue = Object.create(null); t.add_cleanup(function() { - var setter = Object.getOwnPropertyDescriptor( + let setter = Object.getOwnPropertyDescriptor( Object.prototype, '__proto__' ).set; @@ -2057,7 +2177,22 @@ } catch (err) {} }); - assert_throws_js(TypeError, function() { + // We need to find the actual setter for the '__proto__' property, so we + // can determine the right global for it. Walk up the prototype chain + // looking for that property until we find it. + let setter; + { + let cur = obj; + while (cur) { + const desc = Object.getOwnPropertyDescriptor(cur, "__proto__"); + if (desc) { + setter = desc.set; + break; + } + cur = Object.getPrototypeOf(cur); + } + } + assert_throws_js(globalOf(setter).TypeError, function() { obj.__proto__ = newValue; }); @@ -2190,7 +2325,7 @@ assert_own_property(this.get_interface_object(), "prototype", 'interface "' + this.name + '" does not have own property "prototype"'); - if (member["static"]) { + if (member.special === "static") { assert_own_property(this.get_interface_object(), member.name, "The interface object must have a property " + format_value(member.name)); @@ -2238,6 +2373,7 @@ if (!member.has_extended_attribute("LenientThis")) { if (member.idlType.generic !== "Promise") { + // this.get_interface_object() returns a thing in our global assert_throws_js(TypeError, function() { this.get_interface_object().prototype[member.name]; }.bind(this), "getting property on prototype object must throw TypeError"); @@ -2245,7 +2381,7 @@ // do, since it will call done() on a_test. this.do_interface_attribute_asserts(this.get_interface_object().prototype, member, a_test); } else { - promise_rejects(a_test, new TypeError(), + promise_rejects_js(a_test, TypeError, this.get_interface_object().prototype[member.name]) .then(function() { // do_interface_attribute_asserts must be the last @@ -2307,7 +2443,7 @@ var memberHolderObject; // "* If the operation is static, then the property exists on the // interface object." - if (member["static"]) { + if (member.special === "static") { assert_own_property(this.get_interface_object(), member.name, "interface object missing static operation"); memberHolderObject = this.get_interface_object(); @@ -2400,7 +2536,7 @@ // check for globals, since otherwise we'll invoke window.close(). And we // have to skip this test for anything that on the proto chain of "self", // since that does in fact have implicit-this behavior. - if (!member["static"]) { + if (member.special !== "static") { var cb; if (!this.is_global() && memberHolderObject[member.name] != self[member.name]) @@ -2522,7 +2658,7 @@ "property has wrong .length"); // "Let O be the result of calling ToObject on the this value." - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(interfacePrototypeObject.toString).TypeError, function() { interfacePrototypeObject.toString.apply(null, []); }, "calling stringifier with this = null didn't throw TypeError"); @@ -2531,7 +2667,7 @@ // // TODO: Test a platform object that implements some other // interface. (Have to be sure to get inheritance right.) - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(interfacePrototypeObject.toString).TypeError, function() { interfacePrototypeObject.toString.apply({}, []); }, "calling stringifier with this = {} didn't throw TypeError"); }.bind(this), this.name + " interface: stringifier"); @@ -2571,7 +2707,7 @@ { this.test_member_attribute(member); } - if (member.stringifier) { + if (member.special === "stringifier") { this.test_member_stringifier(member); } break; @@ -2586,7 +2722,7 @@ { this.test_member_operation(member); } - } else if (member.stringifier) { + } else if (member.special === "stringifier") { this.test_member_stringifier(member); } break; @@ -2756,7 +2892,7 @@ { assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); - if (!member["static"]) { + if (member.special !== "static") { if (!this.is_global()) { assert_inherits(obj, member.name); } else { @@ -2806,7 +2942,7 @@ assert_equals(exception, null, "Unexpected exception when evaluating object"); assert_equals(typeof obj, expected_typeof, "wrong typeof object"); var fn; - if (!member["static"]) { + if (member.special !== "static") { if (!this.is_global() && !member.isUnforgeable) { assert_inherits(obj, member.name); } else { @@ -2849,7 +2985,7 @@ // default stringifer return true; } - if (this.members.some(function(member) { return member.stringifier; })) { + if (this.members.some(function(member) { return member.special === "stringifier"; })) { return true; } if (this.base && @@ -2903,19 +3039,19 @@ assert_equals(typeof desc.get, "function", "getter must be Function"); // "If the attribute is a regular attribute, then:" - if (!member["static"]) { + if (member.special !== "static") { // "If O is not a platform object that implements I, then: // "If the attribute was specified with the [LenientThis] extended // attribute, then return undefined. // "Otherwise, throw a TypeError." if (!member.has_extended_attribute("LenientThis")) { if (member.idlType.generic !== "Promise") { - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(desc.get).TypeError, function() { desc.get.call({}); }.bind(this), "calling getter on wrong object type must throw TypeError"); } else { pendingPromises.push( - promise_rejects(a_test, new TypeError(), desc.get.call({}), + promise_rejects_js(a_test, TypeError, desc.get.call({}), "calling getter on wrong object type must reject the return promise with TypeError")); } } else { @@ -2953,7 +3089,7 @@ assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes"); // "If the attribute is a regular attribute, then:" - if (!member["static"]) { + if (member.special !== "static") { // "If /validThis/ is false and the attribute was not specified // with the [LenientThis] extended attribute, then throw a // TypeError." @@ -2961,7 +3097,7 @@ // attribute, then: ..." // "If validThis is false, then return." if (!member.has_extended_attribute("LenientThis")) { - assert_throws_js(TypeError, function() { + assert_throws_js(globalOf(desc.set).TypeError, function() { desc.set.call({}); }.bind(this), "calling setter on wrong object type must throw TypeError"); } else { @@ -2991,7 +3127,7 @@ * We just forward all properties to this object without modification, * except for special extAttrs handling. */ - for (var k in obj) + for (var k in obj.toJSON()) { this[k] = obj[k]; } @@ -3006,8 +3142,12 @@ IdlInterfaceMember.prototype = Object.create(IdlObject.prototype); +IdlInterfaceMember.prototype.toJSON = function() { + return this; +}; + IdlInterfaceMember.prototype.is_to_json_regular_operation = function() { - return this.type == "operation" && !this.static && this.name == "toJSON"; + return this.type == "operation" && this.special !== "static" && this.name == "toJSON"; }; /// Internal helper functions /// @@ -3067,6 +3207,24 @@ IdlEnum.prototype = Object.create(IdlObject.prototype); +/// IdlCallback /// +// Used for IdlArray.prototype.assert_type_is +function IdlCallback(obj) +{ + /** + * obj is an object produced by the WebIDLParser.js "callback" + * production. + */ + + /** Self-explanatory. */ + this.name = obj.name; + + /** Arguments for the callback. */ + this.arguments = obj.arguments; +} + +IdlCallback.prototype = Object.create(IdlObject.prototype); + /// IdlTypedef /// // Used for IdlArray.prototype.assert_type_is function IdlTypedef(obj) @@ -3228,16 +3386,30 @@ srcs = (srcs instanceof Array) ? srcs : [srcs] || []; deps = (deps instanceof Array) ? deps : [deps] || []; var setup_error = null; + const validationIgnored = [ + "constructor-member", + "dict-arg-default", + "require-exposed" + ]; return Promise.all( - srcs.concat(deps).map(function(spec) { - return fetch_spec(spec); - })) - .then(function(idls) { + srcs.concat(deps).map(fetch_spec)) + .then(function(results) { + const astArray = results.map(result => + WebIDL2.parse(result.idl, { sourceName: result.spec }) + ); + test(() => { + const validations = WebIDL2.validate(astArray) + .filter(v => !validationIgnored.includes(v.ruleName)); + if (validations.length) { + const message = validations.map(v => v.message).join("\n\n"); + throw new Error(message); + } + }, "idl_test validation"); for (var i = 0; i < srcs.length; i++) { - idl_array.add_idls(idls[i]); + idl_array.internal_add_idls(astArray[i]); } for (var i = srcs.length; i < srcs.length + deps.length; i++) { - idl_array.add_dependency_idls(idls[i]); + idl_array.internal_add_dependency_idls(astArray[i]); } }) .then(function() { @@ -3272,6 +3444,6 @@ throw new IdlHarnessError("Error fetching " + url + "."); } return r.text(); - }); + }).then(idl => ({ spec, idl })); } // vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
diff --git a/third_party/blink/web_tests/resources/testharness.js b/third_party/blink/web_tests/resources/testharness.js index e183e8cf..9d31d0b6 100644 --- a/third_party/blink/web_tests/resources/testharness.js +++ b/third_party/blink/web_tests/resources/testharness.js
@@ -638,29 +638,23 @@ }); } - function promise_rejects(test, expected, promise, description) { + function promise_rejects_js(test, constructor, promise, description) { return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws(expected, function() { throw e }, description); - }); - } - - function promise_rejects_js(test, expected, promise, description) { - return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_js_impl(expected, function() { throw e }, + assert_throws_js_impl(constructor, function() { throw e }, description, "promise_reject_js"); }); } - function promise_rejects_dom(test, expected, promise, description) { + function promise_rejects_dom(test, type, promise, description) { return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_dom_impl(expected, function() { throw e }, + assert_throws_dom_impl(type, function() { throw e }, description, "promise_rejects_dom"); }); } - function promise_rejects_exactly(test, expected, promise, description) { + function promise_rejects_exactly(test, exception, promise, description) { return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_exactly_impl(expected, function() { throw e }, + assert_throws_exactly_impl(exception, function() { throw e }, description, "promise_rejects_exactly"); }); } @@ -849,7 +843,7 @@ // descriptive than the generic message defined here. if (tests.status.status === null) { tests.status.status = tests.status.ERROR; - tests.status.message = "done() was called without first defining any tests: " + new Error().stack; + tests.status.message = "done() was called without first defining any tests"; } tests.complete(); @@ -898,7 +892,6 @@ expose(test, 'test'); expose(async_test, 'async_test'); expose(promise_test, 'promise_test'); - expose(promise_rejects, 'promise_rejects'); expose(promise_rejects_js, 'promise_rejects_js'); expose(promise_rejects_dom, 'promise_rejects_dom'); expose(promise_rejects_exactly, 'promise_rejects_exactly'); @@ -1468,156 +1461,6 @@ expose(assert_readonly, "assert_readonly"); /** - * Assert an Exception with the expected code is thrown. - * - * @param {object|number|string} code The expected exception code. - * @param {Function} func Function which should throw. - * @param {string} description Error description for the case that the error is not thrown. - */ - function assert_throws(code, func, description) - { - try { - func.call(this); - assert(false, "assert_throws", description, - "${func} did not throw", {func:func}); - } catch (e) { - if (e instanceof AssertionError) { - throw e; - } - - assert(typeof e === "object", - "assert_throws", description, - "${func} threw ${e} with type ${type}, not an object", - {func:func, e:e, type:typeof e}); - - assert(e !== null, - "assert_throws", description, - "${func} threw null, not an object", - {func:func}); - - if (code === null) { - throw new AssertionError('Test bug: need to pass exception to assert_throws()'); - } - if (typeof code === "object") { - assert("name" in e && e.name == code.name, - "assert_throws", description, - "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})", - {func:func, actual:e, actual_name:e.name, - expected:code, - expected_name:code.name}); - return; - } - - var code_name_map = { - INDEX_SIZE_ERR: 'IndexSizeError', - HIERARCHY_REQUEST_ERR: 'HierarchyRequestError', - WRONG_DOCUMENT_ERR: 'WrongDocumentError', - INVALID_CHARACTER_ERR: 'InvalidCharacterError', - NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError', - NOT_FOUND_ERR: 'NotFoundError', - NOT_SUPPORTED_ERR: 'NotSupportedError', - INUSE_ATTRIBUTE_ERR: 'InUseAttributeError', - INVALID_STATE_ERR: 'InvalidStateError', - SYNTAX_ERR: 'SyntaxError', - INVALID_MODIFICATION_ERR: 'InvalidModificationError', - NAMESPACE_ERR: 'NamespaceError', - INVALID_ACCESS_ERR: 'InvalidAccessError', - TYPE_MISMATCH_ERR: 'TypeMismatchError', - SECURITY_ERR: 'SecurityError', - NETWORK_ERR: 'NetworkError', - ABORT_ERR: 'AbortError', - URL_MISMATCH_ERR: 'URLMismatchError', - QUOTA_EXCEEDED_ERR: 'QuotaExceededError', - TIMEOUT_ERR: 'TimeoutError', - INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError', - DATA_CLONE_ERR: 'DataCloneError' - }; - - var name = code in code_name_map ? code_name_map[code] : code; - - var name_code_map = { - IndexSizeError: 1, - HierarchyRequestError: 3, - WrongDocumentError: 4, - InvalidCharacterError: 5, - NoModificationAllowedError: 7, - NotFoundError: 8, - NotSupportedError: 9, - InUseAttributeError: 10, - InvalidStateError: 11, - SyntaxError: 12, - InvalidModificationError: 13, - NamespaceError: 14, - InvalidAccessError: 15, - TypeMismatchError: 17, - SecurityError: 18, - NetworkError: 19, - AbortError: 20, - URLMismatchError: 21, - QuotaExceededError: 22, - TimeoutError: 23, - InvalidNodeTypeError: 24, - DataCloneError: 25, - - EncodingError: 0, - NotReadableError: 0, - UnknownError: 0, - ConstraintError: 0, - DataError: 0, - TransactionInactiveError: 0, - ReadOnlyError: 0, - VersionError: 0, - OperationError: 0, - NotAllowedError: 0 - }; - - var code_name_map = {}; - for (var key in name_code_map) { - if (name_code_map[key] > 0) { - code_name_map[name_code_map[key]] = key; - } - } - - var required_props = { code: code }; - - if (typeof code === "number") { - if (code === 0) { - throw new AssertionError('Test bug: ambiguous DOMException code 0 passed to assert_throws()'); - } else if (!(code in code_name_map)) { - throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()'); - } - name = code_name_map[code]; - } else if (typeof code === "string") { - if (!(name in name_code_map)) { - throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()'); - } - required_props.code = name_code_map[name]; - } - - if (required_props.code === 0 || - ("name" in e && - e.name !== e.name.toUpperCase() && - e.name !== "DOMException")) { - // New style exception: also test the name property. - required_props.name = name; - } - - //We'd like to test that e instanceof the appropriate interface, - //but we can't, because we don't know what window it was created - //in. It might be an instanceof the appropriate interface on some - //unknown other window. TODO: Work around this somehow? - - for (var prop in required_props) { - assert(prop in e && e[prop] == required_props[prop], - "assert_throws", description, - "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}", - {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]}); - } - } - } - expose(assert_throws, "assert_throws"); - - /** * Assert a JS Error with the expected constructor is thrown. * * @param {object} constructor The expected exception constructor.
diff --git a/third_party/blink/web_tests/resources/webidl2.js b/third_party/blink/web_tests/resources/webidl2.js index ef519c0..ea30d6e 100644 --- a/third_party/blink/web_tests/resources/webidl2.js +++ b/third_party/blink/web_tests/resources/webidl2.js
@@ -1,970 +1,2873 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["WebIDL2"] = factory(); + else + root["WebIDL2"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + "use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__["parse"]; }); -(() => { - // These regular expressions use the sticky flag so they will only match at - // the current location (ie. the offset of lastIndex). - const tokenRe = { - // This expression uses a lookahead assertion to catch false matches - // against integers early. - "float": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y, - "integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y, - "identifier": /_?[A-Za-z][0-9A-Z_a-z-]*/y, - "string": /"[^"]*"/y, - "whitespace": /[\t\n\r ]+/y, - "comment": /((\/(\/.*|\*([^*]|\*[^\/])*\*\/)[\t\n\r ]*)+)/y, - "other": /[^\t\n\r 0-9A-Za-z]/y - }; +/* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "write", function() { return _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__["write"]; }); - const stringTypes = [ - "ByteString", - "DOMString", - "USVString" - ]; +/* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__["validate"]; }); - const argumentNameKeywords = [ - "attribute", - "callback", - "const", - "deleter", - "dictionary", - "enum", - "getter", - "includes", - "inherit", - "interface", - "iterable", - "maplike", - "namespace", - "partial", - "required", - "setlike", - "setter", - "static", - "stringifier", - "typedef", - "unrestricted" - ]; - const nonRegexTerminals = [ - "FrozenArray", - "Infinity", - "NaN", - "Promise", - "boolean", - "byte", - "double", - "false", - "float", - "implements", - "legacyiterable", - "long", - "mixin", - "null", - "octet", - "optional", - "or", - "readonly", - "record", - "sequence", - "short", - "true", - "unsigned", - "void" - ].concat(argumentNameKeywords, stringTypes); - const punctuations = [ - "(", - ")", - ",", - "-Infinity", - "...", - ":", - ";", - "<", - "=", - ">", - "?", - "[", - "]", - "{", - "}" - ]; - function tokenise(str) { - const tokens = []; - let lastIndex = 0; - let trivia = ""; - while (lastIndex < str.length) { - const nextChar = str.charAt(lastIndex); - let result = -1; - if (/[\t\n\r ]/.test(nextChar)) { - result = attemptTokenMatch("whitespace", { noFlushTrivia: true }); - } else if (nextChar === '/') { - result = attemptTokenMatch("comment", { noFlushTrivia: true }); + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; }); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); +/* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15); +/* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); +/* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); +/* harmony import */ var _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); +/* harmony import */ var _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18); +/* harmony import */ var _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19); +/* harmony import */ var _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(25); +/* harmony import */ var _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(26); +/* harmony import */ var _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(28); +/* harmony import */ var _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(29); + + + + + + + + + + + + + + +/** + * @param {Tokeniser} tokeniser + * @param {object} options + * @param {boolean} [options.concrete] + */ +function parseByTokens(tokeniser, options) { + const source = tokeniser.source; + + function error(str) { + tokeniser.error(str); + } + + function consume(...candidates) { + return tokeniser.consume(...candidates); + } + + function callback() { + const callback = consume("callback"); + if (!callback) return; + if (tokeniser.probe("interface")) { + return _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__["CallbackInterface"].parse(tokeniser, callback); + } + return _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__["CallbackFunction"].parse(tokeniser, callback); + } + + function interface_(opts) { + const base = consume("interface"); + if (!base) return; + const ret = _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__["Mixin"].parse(tokeniser, base, opts) || + _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__["Interface"].parse(tokeniser, base, opts) || + error("Interface has no proper body"); + return ret; + } + + function partial() { + const partial = consume("partial"); + if (!partial) return; + return _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser, { partial }) || + interface_({ partial }) || + _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser, { partial }) || + error("Partial doesn't apply to anything"); + } + + function definition() { + return callback() || + interface_() || + partial() || + _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser) || + _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__["Enum"].parse(tokeniser) || + _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__["Typedef"].parse(tokeniser) || + _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__["Includes"].parse(tokeniser) || + _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser); + } + + function definitions() { + if (!source.length) return []; + const defs = []; + while (true) { + const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser); + const def = definition(); + if (!def) { + if (ea.length) error("Stray extended attributes"); + break; } + def.extAttrs = ea; + defs.push(def); + } + const eof = consume("eof"); + if (options.concrete) { + defs.push(eof); + } + return defs; + } + const res = definitions(); + if (tokeniser.position < source.length) error("Unrecognised tokens"); + return res; +} - if (result !== -1) { - trivia += tokens.pop().value; - } else if (/[-0-9.]/.test(nextChar)) { - result = attemptTokenMatch("float"); - if (result === -1) { - result = attemptTokenMatch("integer"); - } - } else if (/[A-Z_a-z]/.test(nextChar)) { +function parse(str, options = {}) { + const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__["Tokeniser"](str); + if (typeof options.sourceName !== "undefined") { + tokeniser.source.name = options.sourceName; + } + return parseByTokens(tokeniser, options); +} + + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringTypes", function() { return stringTypes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argumentNameKeywords", function() { return argumentNameKeywords; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Tokeniser", function() { return Tokeniser; }); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); +/* harmony import */ var _productions_helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +// These regular expressions use the sticky flag so they will only match at +// the current location (ie. the offset of lastIndex). +const tokenRe = { + // This expression uses a lookahead assertion to catch false matches + // against integers early. + "decimal": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y, + "integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y, + "identifier": /[_-]?[A-Za-z][0-9A-Z_a-z-]*/y, + "string": /"[^"]*"/y, + "whitespace": /[\t\n\r ]+/y, + "comment": /((\/(\/.*|\*([^*]|\*[^/])*\*\/)[\t\n\r ]*)+)/y, + "other": /[^\t\n\r 0-9A-Za-z]/y +}; + +const stringTypes = [ + "ByteString", + "DOMString", + "USVString" +]; + +const argumentNameKeywords = [ + "async", + "attribute", + "callback", + "const", + "constructor", + "deleter", + "dictionary", + "enum", + "getter", + "includes", + "inherit", + "interface", + "iterable", + "maplike", + "namespace", + "partial", + "required", + "setlike", + "setter", + "static", + "stringifier", + "typedef", + "unrestricted" +]; + +const nonRegexTerminals = [ + "-Infinity", + "FrozenArray", + "Infinity", + "NaN", + "Promise", + "async", + "boolean", + "byte", + "constructor", + "double", + "false", + "float", + "long", + "mixin", + "null", + "octet", + "optional", + "or", + "readonly", + "record", + "sequence", + "short", + "true", + "unsigned", + "void" +].concat(argumentNameKeywords, stringTypes); + +const punctuations = [ + "(", + ")", + ",", + "...", + ":", + ";", + "<", + "=", + ">", + "?", + "[", + "]", + "{", + "}" +]; + +const reserved = [ + // "constructor" is now a keyword + "_constructor", + "toString", + "_toString", +]; + +/** + * @param {string} str + */ +function tokenise(str) { + const tokens = []; + let lastCharIndex = 0; + let trivia = ""; + let line = 1; + let index = 0; + while (lastCharIndex < str.length) { + const nextChar = str.charAt(lastCharIndex); + let result = -1; + + if (/[\t\n\r ]/.test(nextChar)) { + result = attemptTokenMatch("whitespace", { noFlushTrivia: true }); + } else if (nextChar === '/') { + result = attemptTokenMatch("comment", { noFlushTrivia: true }); + } + + if (result !== -1) { + const currentTrivia = tokens.pop().value; + line += (currentTrivia.match(/\n/g) || []).length; + trivia += currentTrivia; + index -= 1; + } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) { + result = attemptTokenMatch("decimal"); + if (result === -1) { + result = attemptTokenMatch("integer"); + } + if (result === -1) { result = attemptTokenMatch("identifier"); - const token = tokens[tokens.length - 1]; - if (result !== -1 && nonRegexTerminals.includes(token.value)) { - token.type = token.value; - } - } else if (nextChar === '"') { - result = attemptTokenMatch("string"); - } - - for (const punctuation of punctuations) { - if (str.startsWith(punctuation, lastIndex)) { - tokens.push({ type: punctuation, value: punctuation, trivia }); - trivia = ""; - lastIndex += punctuation.length; - result = lastIndex; - break; - } - } - - // other as the last try - if (result === -1) { - result = attemptTokenMatch("other"); - } - if (result === -1) { - throw new Error("Token stream not progressing"); - } - lastIndex = result; - } - return tokens; - - function attemptTokenMatch(type, { noFlushTrivia } = {}) { - const re = tokenRe[type]; - re.lastIndex = lastIndex; - const result = re.exec(str); - if (result) { - tokens.push({ type, value: result[0], trivia }); - if (!noFlushTrivia) { - trivia = ""; - } - return re.lastIndex; - } - return -1; - } - } - - class WebIDLParseError { - constructor(str, line, input, tokens) { - this.message = str; - this.line = line; - this.input = input; - this.tokens = tokens; - } - - toString() { - const escapedInput = JSON.stringify(this.input); - const tokens = JSON.stringify(this.tokens, null, 4); - return `${this.message}, line ${this.line} (tokens: ${escapedInput})\n${tokens}`; - } - } - - function parse(tokens) { - let line = 1; - tokens = tokens.slice(); - const names = new Map(); - let current = null; - - const FLOAT = "float"; - const INT = "integer"; - const ID = "identifier"; - const STR = "string"; - const OTHER = "other"; - - const EMPTY_OPERATION = Object.freeze({ - type: "operation", - getter: false, - setter: false, - deleter: false, - static: false, - stringifier: false - }); - - const EMPTY_IDLTYPE = Object.freeze({ - generic: null, - nullable: false, - union: false, - idlType: null, - extAttrs: [] - }); - - function error(str) { - const maxTokens = 5; - const tok = tokens - .slice(consume_position, consume_position + maxTokens) - .map(t => t.trivia + t.value).join(""); - // Count newlines preceding the actual erroneous token - if (tokens.length) { - line += count(tokens[consume_position].trivia, "\n"); - } - - let message; - if (current) { - message = `Got an error during or right after parsing \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`: ${str}` - } - else { - // throwing before any valid definition - message = `Got an error before parsing any named definition: ${str}`; - } - - throw new WebIDLParseError(message, line, tok, tokens.slice(0, maxTokens)); - } - - function sanitize_name(name, type) { - if (names.has(name)) { - error(`The name "${name}" of type "${names.get(name)}" is already seen`); - } - names.set(name, type); - return name; - } - - let consume_position = 0; - - function probe(type) { - return tokens.length > consume_position && tokens[consume_position].type === type; - } - - function consume(...candidates) { - // TODO: use const when Servo updates its JS engine - for (let type of candidates) { - if (!probe(type)) continue; - const token = tokens[consume_position]; - consume_position++; - line += count(token.trivia, "\n"); - return token; - } - } - - function unescape(identifier) { - return identifier.startsWith('_') ? identifier.slice(1) : identifier; - } - - function unconsume(position) { - while (consume_position > position) { - consume_position--; - line -= count(tokens[consume_position].trivia, "\n"); - } - } - - function count(str, char) { - let total = 0; - for (let i = str.indexOf(char); i !== -1; i = str.indexOf(char, i + 1)) { - ++total; - } - return total; - } - - function integer_type() { - let ret = ""; - if (consume("unsigned")) ret = "unsigned "; - if (consume("short")) return ret + "short"; - if (consume("long")) { - ret += "long"; - if (consume("long")) return ret + " long"; - return ret; - } - if (ret) error("Failed to parse integer type"); - } - - function float_type() { - let ret = ""; - if (consume("unrestricted")) ret = "unrestricted "; - if (consume("float")) return ret + "float"; - if (consume("double")) return ret + "double"; - if (ret) error("Failed to parse float type"); - } - - function primitive_type() { - const num_type = integer_type() || float_type(); - if (num_type) return num_type; - if (consume("boolean")) return "boolean"; - if (consume("byte")) return "byte"; - if (consume("octet")) return "octet"; - } - - function const_value() { - if (consume("true")) return { type: "boolean", value: true }; - if (consume("false")) return { type: "boolean", value: false }; - if (consume("null")) return { type: "null" }; - if (consume("Infinity")) return { type: "Infinity", negative: false }; - if (consume("-Infinity")) return { type: "Infinity", negative: true }; - if (consume("NaN")) return { type: "NaN" }; - const ret = consume(FLOAT, INT); - if (ret) return { type: "number", value: ret.value }; - } - - function type_suffix(obj) { - obj.nullable = !!consume("?"); - if (probe("?")) error("Can't nullable more than once"); - } - - function generic_type(typeName) { - const name = consume("FrozenArray", "Promise", "sequence", "record"); - if (!name) { - return; - } - const ret = { generic: name.type }; - consume("<") || error(`No opening bracket after ${name.type}`); - switch (name.type) { - case "Promise": - if (probe("[")) error("Promise type cannot have extended attribute"); - ret.idlType = return_type(typeName); - break; - case "sequence": - case "FrozenArray": - ret.idlType = type_with_extended_attributes(typeName); - break; - case "record": - if (probe("[")) error("Record key cannot have extended attribute"); - ret.idlType = []; - const keyType = consume(...stringTypes); - if (!keyType) error(`Record key must be a string type`); - ret.idlType.push(Object.assign({ type: typeName }, EMPTY_IDLTYPE, { idlType: keyType.value })); - consume(",") || error("Missing comma after record key type"); - const valueType = type_with_extended_attributes(typeName) || error("Error parsing generic type record"); - ret.idlType.push(valueType); - break; - } - if (!ret.idlType) error(`Error parsing generic type ${name.type}`); - consume(">") || error(`Missing closing bracket after ${name.type}`); - if (name.type === "Promise" && probe("?")) { - error("Promise type cannot be nullable"); - } - type_suffix(ret); - return ret; - } - - function single_type(typeName) { - const ret = Object.assign({ type: typeName || null }, EMPTY_IDLTYPE); - const generic = generic_type(typeName); - if (generic) { - return Object.assign(ret, generic); - } - const prim = primitive_type(); - let name; - if (prim) { - ret.idlType = prim; - } else if (name = consume(ID, ...stringTypes)) { - ret.idlType = name.value; - if (probe("<")) error(`Unsupported generic type ${name.value}`); - } else { - return; - } - type_suffix(ret); - if (ret.nullable && ret.idlType === "any") error("Type any cannot be made nullable"); - return ret; - } - - function union_type(typeName) { - if (!consume("(")) return; - const ret = Object.assign({ type: typeName || null }, EMPTY_IDLTYPE, { union: true, idlType: [] }); - do { - const typ = type_with_extended_attributes() || error("No type after open parenthesis or 'or' in union type"); - ret.idlType.push(typ); - } while (consume("or")); - if (ret.idlType.length < 2) { - error("At least two types are expected in a union type but found less"); - } - if (!consume(")")) error("Unterminated union type"); - type_suffix(ret); - return ret; - } - - function type(typeName) { - return single_type(typeName) || union_type(typeName); - } - - function type_with_extended_attributes(typeName) { - const extAttrs = extended_attrs(); - const ret = single_type(typeName) || union_type(typeName); - if (extAttrs.length && ret) ret.extAttrs = extAttrs; - return ret; - } - - function argument() { - const start_position = consume_position; - const ret = { optional: false, variadic: false, default: null }; - ret.extAttrs = extended_attrs(); - const opt_token = consume("optional"); - if (opt_token) { - ret.optional = true; - } - ret.idlType = type_with_extended_attributes("argument-type"); - if (!ret.idlType) { - unconsume(start_position); - return; - } - if (!ret.optional && consume("...")) { - ret.variadic = true; - } - const name = consume(ID, ...argumentNameKeywords); - if (!name) { - unconsume(start_position); - return; - } - ret.name = unescape(name.value); - ret.escapedName = name.value; - if (ret.optional) { - ret.default = default_() || null; - } - return ret; - } - - function argument_list() { - const ret = []; - const arg = argument(); - if (!arg) return ret; - ret.push(arg); - while (true) { - if (!consume(",")) return ret; - const nxt = argument() || error("Trailing comma in arguments list"); - ret.push(nxt); - } - } - - function simple_extended_attr() { - const name = consume(ID); - if (!name) return; - const ret = { - name: name.value, - arguments: null, - type: "extended-attribute", - rhs: null - }; - const eq = consume("="); - if (eq) { - ret.rhs = consume(ID, FLOAT, INT, STR); - if (ret.rhs) { - // No trivia exposure yet - ret.rhs.trivia = undefined; - } - } - if (consume("(")) { - if (eq && !ret.rhs) { - // [Exposed=(Window,Worker)] - ret.rhs = { - type: "identifier-list", - value: identifiers() - }; - } - else { - // [NamedConstructor=Audio(DOMString src)] or [Constructor(DOMString str)] - ret.arguments = argument_list(); - } - consume(")") || error("Unexpected token in extended attribute argument list"); - } - if (eq && !ret.rhs) error("No right hand side to extended attribute assignment"); - return ret; - } - - // Note: we parse something simpler than the official syntax. It's all that ever - // seems to be used - function extended_attrs() { - const eas = []; - if (!consume("[")) return eas; - eas[0] = simple_extended_attr() || error("Extended attribute with not content"); - while (consume(",")) { - eas.push(simple_extended_attr() || error("Trailing comma in extended attribute")); - } - consume("]") || error("No end of extended attribute"); - return eas; - } - - function default_() { - if (consume("=")) { - const def = const_value(); - if (def) { - return def; - } else if (consume("[")) { - if (!consume("]")) error("Default sequence value must be empty"); - return { type: "sequence", value: [] }; - } else { - const str = consume(STR) || error("No value for default"); - str.value = str.value.slice(1, -1); - // No trivia exposure yet - str.trivia = undefined; - return str; - } - } - } - - function const_() { - if (!consume("const")) return; - const ret = { type: "const", nullable: false }; - let typ = primitive_type(); - if (!typ) { - typ = consume(ID) || error("No type for const"); - typ = typ.value; - } - ret.idlType = Object.assign({ type: "const-type" }, EMPTY_IDLTYPE, { idlType: typ }); - type_suffix(ret); - const name = consume(ID) || error("No name for const"); - ret.name = name.value; - consume("=") || error("No value assignment for const"); - const cnt = const_value(); - if (cnt) ret.value = cnt; - else error("No value for const"); - consume(";") || error("Unterminated const"); - return ret; - } - - function inheritance() { - if (consume(":")) { - const inh = consume(ID) || error("No type in inheritance"); - return inh.value; - } - } - - function operation_rest(ret) { - if (!ret) ret = {}; - const name = consume(ID); - ret.name = name ? unescape(name.value) : null; - ret.escapedName = name ? name.value : null; - consume("(") || error("Invalid operation"); - ret.arguments = argument_list(); - consume(")") || error("Unterminated operation"); - consume(";") || error("Unterminated operation"); - return ret; - } - - function callback() { - let ret; - if (!consume("callback")) return; - const tok = consume("interface"); - if (tok) { - ret = interface_rest(false, "callback interface"); - return ret; - } - const name = consume(ID) || error("No name for callback"); - ret = current = { type: "callback", name: sanitize_name(name.value, "callback") }; - consume("=") || error("No assignment in callback"); - ret.idlType = return_type() || error("Missing return type"); - consume("(") || error("No arguments in callback"); - ret.arguments = argument_list(); - consume(")") || error("Unterminated callback"); - consume(";") || error("Unterminated callback"); - return ret; - } - - function attribute({ noInherit = false, readonly = false } = {}) { - const start_position = consume_position; - const ret = { - type: "attribute", - static: false, - stringifier: false, - inherit: false, - readonly: false - }; - if (!noInherit && consume("inherit")) { - ret.inherit = true; - } - if (consume("readonly")) { - ret.readonly = true; - } else if (readonly && probe("attribute")) { - error("Attributes must be readonly in this context"); - } - const rest = attribute_rest(ret); - if (!rest) { - unconsume(start_position); - } - return rest; - } - - function attribute_rest(ret) { - if (!consume("attribute")) { - return; - } - ret.idlType = type_with_extended_attributes("attribute-type") || error("No type in attribute"); - if (ret.idlType.generic === "sequence") error("Attributes cannot accept sequence types"); - if (ret.idlType.generic === "record") error("Attributes cannot accept record types"); - const name = consume(ID, "required") || error("No name in attribute"); - ret.name = unescape(name.value); - ret.escapedName = name.value; - consume(";") || error("Unterminated attribute"); - return ret; - } - - function return_type(typeName) { - const typ = type(typeName || "return-type"); - if (typ) { - return typ; - } - if (consume("void")) { - return Object.assign({ type: "return-type" }, EMPTY_IDLTYPE, { idlType: "void" }); - } - } - - function operation({ regular = false } = {}) { - const ret = Object.assign({}, EMPTY_OPERATION); - while (!regular) { - if (consume("getter")) ret.getter = true; - else if (consume("setter")) ret.setter = true; - else if (consume("deleter")) ret.deleter = true; - else break; - } - ret.idlType = return_type() || error("Missing return type"); - operation_rest(ret); - return ret; - } - - function static_member() { - if (!consume("static")) return; - const member = attribute({ noInherit: true }) || - operation({ regular: true }) || - error("No body in static member"); - member.static = true; - return member; - } - - function stringifier() { - if (!consume("stringifier")) return; - if (consume(";")) { - return Object.assign({}, EMPTY_OPERATION, { stringifier: true }); - } - const member = attribute({ noInherit: true }) || - operation({ regular: true }) || - error("Unterminated stringifier"); - member.stringifier = true; - return member; - } - - function identifiers() { - const arr = []; - const id = consume(ID); - if (id) { - arr.push(id.value); - } - else error("Expected identifiers but not found"); - while (true) { - if (consume(",")) { - const name = consume(ID) || error("Trailing comma in identifiers list"); - arr.push(name.value); - } else break; - } - return arr; - } - - function iterable_type() { - if (consume("iterable")) return "iterable"; - else if (consume("legacyiterable")) return "legacyiterable"; - else if (consume("maplike")) return "maplike"; - else if (consume("setlike")) return "setlike"; - else return; - } - - function readonly_iterable_type() { - if (consume("maplike")) return "maplike"; - else if (consume("setlike")) return "setlike"; - else return; - } - - function iterable() { - const start_position = consume_position; - const ret = { type: null, idlType: null, readonly: false }; - if (consume("readonly")) { - ret.readonly = true; - } - const consumeItType = ret.readonly ? readonly_iterable_type : iterable_type; - - const ittype = consumeItType(); - if (!ittype) { - unconsume(start_position); - return; - } - - const secondTypeRequired = ittype === "maplike"; - const secondTypeAllowed = secondTypeRequired || ittype === "iterable"; - ret.type = ittype; - if (ret.type !== 'maplike' && ret.type !== 'setlike') - delete ret.readonly; - if (consume("<")) { - ret.idlType = [type_with_extended_attributes()] || error(`Error parsing ${ittype} declaration`); - if (secondTypeAllowed) { - if (consume(",")) { - ret.idlType.push(type_with_extended_attributes()); + const lastIndex = tokens.length - 1; + const token = tokens[lastIndex]; + if (result !== -1) { + if (reserved.includes(token.value)) { + const message = `${Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(token.value)} is a reserved identifier and must not be used.`; + throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(tokens, lastIndex, null, message)); + } else if (nonRegexTerminals.includes(token.value)) { + token.type = token.value; } - else if (secondTypeRequired) - error(`Missing second type argument in ${ittype} declaration`); } - if (!consume(">")) error(`Unterminated ${ittype} declaration`); - if (!consume(";")) error(`Missing semicolon after ${ittype} declaration`); - } else - error(`Error parsing ${ittype} declaration`); - - return ret; + } + } else if (nextChar === '"') { + result = attemptTokenMatch("string"); } - function interface_rest(isPartial, typeName = "interface") { - const name = consume(ID) || error("No name for interface"); - const mems = []; - const ret = current = { - type: typeName, - name: isPartial ? name.value : sanitize_name(name.value, "interface"), - partial: isPartial, - members: mems - }; - if (!isPartial) ret.inheritance = inheritance() || null; - consume("{") || error("Bodyless interface"); - while (true) { - if (consume("}")) { - consume(";") || error("Missing semicolon after interface"); - return ret; - } - const ea = extended_attrs(); - const mem = const_() || - static_member() || - stringifier() || - iterable() || - attribute() || - operation() || - error("Unknown member"); - mem.extAttrs = ea; - ret.members.push(mem); + for (const punctuation of punctuations) { + if (str.startsWith(punctuation, lastCharIndex)) { + tokens.push({ type: punctuation, value: punctuation, trivia, line, index }); + trivia = ""; + lastCharIndex += punctuation.length; + result = lastCharIndex; + break; } } - function mixin_rest(isPartial) { - if (!consume("mixin")) return; - const name = consume(ID) || error("No name for interface mixin"); - const mems = []; - const ret = current = { - type: "interface mixin", - name: isPartial ? name.value : sanitize_name(name.value, "interface mixin"), - partial: isPartial, - members: mems - }; - consume("{") || error("Bodyless interface mixin"); - while (true) { - if (consume("}")) { - consume(";") || error("Missing semicolon after interface mixin"); - return ret; - } - const ea = extended_attrs(); - const mem = const_() || - stringifier() || - attribute({ noInherit: true }) || - operation({ regular: true }) || - error("Unknown member"); - mem.extAttrs = ea; - ret.members.push(mem); - } + // other as the last try + if (result === -1) { + result = attemptTokenMatch("other"); } - - function interface_(isPartial) { - if (!consume("interface")) return; - return mixin_rest(isPartial) || - interface_rest(isPartial) || - error("Interface has no proper body"); + if (result === -1) { + throw new Error("Token stream not progressing"); } - - function namespace(isPartial) { - if (!consume("namespace")) return; - const name = consume(ID) || error("No name for namespace"); - const mems = []; - const ret = current = { - type: "namespace", - name: isPartial ? name.value : sanitize_name(name.value, "namespace"), - partial: isPartial, - members: mems - }; - consume("{") || error("Bodyless namespace"); - while (true) { - if (consume("}")) { - consume(";") || error("Missing semicolon after namespace"); - return ret; - } - const ea = extended_attrs(); - const mem = attribute({ noInherit: true, readonly: true }) || - operation({ regular: true }) || - error("Unknown member"); - mem.extAttrs = ea; - ret.members.push(mem); - } - } - - function partial() { - if (!consume("partial")) return; - const thing = dictionary(true) || - interface_(true) || - namespace(true) || - error("Partial doesn't apply to anything"); - return thing; - } - - function dictionary(isPartial) { - if (!consume("dictionary")) return; - const name = consume(ID) || error("No name for dictionary"); - const mems = []; - const ret = current = { - type: "dictionary", - name: isPartial ? name.value : sanitize_name(name.value, "dictionary"), - partial: isPartial, - members: mems - }; - if (!isPartial) ret.inheritance = inheritance() || null; - consume("{") || error("Bodyless dictionary"); - while (true) { - if (consume("}")) { - consume(";") || error("Missing semicolon after dictionary"); - return ret; - } - const ea = extended_attrs(); - const required = consume("required"); - const typ = type_with_extended_attributes("dictionary-type") || error("No type for dictionary member"); - const name = consume(ID) || error("No name for dictionary member"); - const dflt = default_() || null; - if (required && dflt) error("Required member must not have a default"); - const member = { - type: "field", - name: unescape(name.value), - escapedName: name.value, - required: !!required, - idlType: typ, - extAttrs: ea, - default: dflt - }; - ret.members.push(member); - consume(";") || error("Unterminated dictionary member"); - } - } - - function enum_() { - if (!consume("enum")) return; - const name = consume(ID) || error("No name for enum"); - const vals = []; - const ret = current = { - type: "enum", - name: sanitize_name(name.value, "enum"), - values: vals - }; - consume("{") || error("No curly for enum"); - let value_expected = true; - while (true) { - if (consume("}")) { - if (!ret.values.length) error("No value in enum"); - consume(";") || error("No semicolon after enum"); - return ret; - } - else if (!value_expected) { - error("No comma between enum values"); - } - const val = consume(STR) || error("Unexpected value in enum"); - val.value = val.value.slice(1, -1); - // No trivia exposure yet - val.trivia = undefined; - ret.values.push(val); - value_expected = !!consume(","); - } - } - - function typedef() { - if (!consume("typedef")) return; - const ret = { - type: "typedef" - }; - ret.idlType = type_with_extended_attributes("typedef-type") || error("No type in typedef"); - const name = consume(ID) || error("No name in typedef"); - ret.name = sanitize_name(name.value, "typedef"); - current = ret; - consume(";") || error("Unterminated typedef"); - return ret; - } - - function implements_() { - const start_position = consume_position; - const target = consume(ID); - if (!target) return; - if (consume("implements")) { - const ret = { - type: "implements", - target: target.value - }; - const imp = consume(ID) || error("Incomplete implements statement"); - ret.implements = imp.value; - consume(";") || error("No terminating ; for implements statement"); - return ret; - } else { - // rollback - unconsume(start_position); - } - } - - function includes() { - const start_position = consume_position; - const target = consume(ID); - if (!target) return; - if (consume("includes")) { - const ret = { - type: "includes", - target: target.value - }; - const imp = consume(ID) || error("Incomplete includes statement"); - ret.includes = imp.value; - consume(";") || error("No terminating ; for includes statement"); - return ret; - } else { - // rollback - unconsume(start_position); - } - } - - function definition() { - return callback() || - interface_(false) || - partial() || - dictionary(false) || - enum_() || - typedef() || - implements_() || - includes() || - namespace(false); - } - - function definitions() { - if (!tokens.length) return []; - const defs = []; - while (true) { - const ea = extended_attrs(); - const def = definition(); - if (!def) { - if (ea.length) error("Stray extended attributes"); - break; - } - def.extAttrs = ea; - defs.push(def); - } - return defs; - } - const res = definitions(); - if (consume_position < tokens.length) error("Unrecognised tokens"); - return res; + lastCharIndex = result; + index += 1; } - const obj = { - parse(str) { - const tokens = tokenise(str); - return parse(tokens); + // remaining trivia as eof + tokens.push({ + type: "eof", + value: "", + trivia + }); + + return tokens; + + /** + * @param {keyof tokenRe} type + * @param {object} [options] + * @param {boolean} [options.noFlushTrivia] + */ + function attemptTokenMatch(type, { noFlushTrivia } = {}) { + const re = tokenRe[type]; + re.lastIndex = lastCharIndex; + const result = re.exec(str); + if (result) { + tokens.push({ type, value: result[0], trivia, line, index }); + if (!noFlushTrivia) { + trivia = ""; + } + return re.lastIndex; + } + return -1; + } +} + +class Tokeniser { + /** + * @param {string} idl + */ + constructor(idl) { + this.source = tokenise(idl); + this.position = 0; + } + + /** + * @param {string} message + */ + error(message) { + throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message)); + } + + /** + * @param {string} type + */ + probe(type) { + return this.source.length > this.position && this.source[this.position].type === type; + } + + /** + * @param {...string} candidates + */ + consume(...candidates) { + for (const type of candidates) { + if (!this.probe(type)) continue; + const token = this.source[this.position]; + this.position++; + return token; + } + } + + /** + * @param {number} position + */ + unconsume(position) { + this.position = position; + } +} + +class WebIDLParseError extends Error { + constructor({ message, bareMessage, context, line, sourceName, input, tokens }) { + super(message); + + this.name = "WebIDLParseError"; // not to be mangled + this.bareMessage = bareMessage; + this.context = context; + this.line = line; + this.sourceName = sourceName; + this.input = input; + this.tokens = tokens; + } +} + + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validationError", function() { return validationError; }); +/** + * @param {string} text + */ +function lastLine(text) { + const splitted = text.split("\n"); + return splitted[splitted.length - 1]; +} + +/** + * @typedef {object} WebIDL2ErrorOptions + * @property {"error" | "warning"} level + * @property {Function} autofix + * + * @param {string} message error message + * @param {"Syntax" | "Validation"} kind error type + * @param {WebIDL2ErrorOptions} [options] + */ +function error(source, position, current, message, kind, { level = "error", autofix, ruleName } = {}) { + /** + * @param {number} count + */ + function sliceTokens(count) { + return count > 0 ? + source.slice(position, position + count) : + source.slice(Math.max(position + count, 0), position); + } + + function tokensToText(inputs, { precedes } = {}) { + const text = inputs.map(t => t.trivia + t.value).join(""); + const nextToken = source[position]; + if (nextToken.type === "eof") { + return text; + } + if (precedes) { + return text + nextToken.trivia; + } + return text.slice(nextToken.trivia.length); + } + + const maxTokens = 5; // arbitrary but works well enough + const line = + source[position].type !== "eof" ? source[position].line : + source.length > 1 ? source[position - 1].line : + 1; + + const precedingLastLine = lastLine( + tokensToText(sliceTokens(-maxTokens), { precedes: true }) + ); + + const subsequentTokens = sliceTokens(maxTokens); + const subsequentText = tokensToText(subsequentTokens); + const subsequentFirstLine = subsequentText.split("\n")[0]; + + const spaced = " ".repeat(precedingLastLine.length) + "^"; + const sourceContext = precedingLastLine + subsequentFirstLine + "\n" + spaced; + + const contextType = kind === "Syntax" ? "since" : "inside"; + const inSourceName = source.name ? ` in ${source.name}` : ""; + const grammaticalContext = (current && current.name) ? `, ${contextType} \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`` : ""; + const context = `${kind} error at line ${line}${inSourceName}${grammaticalContext}:\n${sourceContext}`; + return { + message: `${context} ${message}`, + bareMessage: message, + context, + line, + sourceName: source.name, + level, + ruleName, + autofix, + input: subsequentText, + tokens: subsequentTokens + }; +} + +/** + * @param {string} message error message + */ +function syntaxError(source, position, current, message) { + return error(source, position, current, message, "Syntax"); +} + +/** + * @param {string} message error message + * @param {WebIDL2ErrorOptions} [options] + */ +function validationError(token, current, ruleName, message, options = {}) { + options.ruleName = ruleName; + return error(current.source, token.index, current, message, "Validation", options); +} + + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unescape", function() { return unescape; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "list", function() { return list; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_value", function() { return const_value; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "const_data", function() { return const_data; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "primitive_type", function() { return primitive_type; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifiers", function() { return identifiers; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argument_list", function() { return argument_list; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "type_with_extended_attributes", function() { return type_with_extended_attributes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "return_type", function() { return return_type; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringifier", function() { return stringifier; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLastIndentation", function() { return getLastIndentation; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemberIndentation", function() { return getMemberIndentation; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "autofixAddExposedWindow", function() { return autofixAddExposedWindow; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFirstToken", function() { return getFirstToken; }); +/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5); +/* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8); +/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(13); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(14); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2); + + + + + + + + +/** + * @param {string} identifier + */ +function unescape(identifier) { + return identifier.startsWith('_') ? identifier.slice(1) : identifier; +} + +/** + * Parses comma-separated list + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {object} args + * @param {Function} args.parser parser function for each item + * @param {boolean} [args.allowDangler] whether to allow dangling comma + * @param {string} [args.listName] the name to be shown on error messages + */ +function list(tokeniser, { parser, allowDangler, listName = "list" }) { + const first = parser(tokeniser); + if (!first) { + return []; + } + first.tokens.separator = tokeniser.consume(","); + const items = [first]; + while (first.tokens.separator) { + const item = parser(tokeniser); + if (!item) { + if (!allowDangler) { + tokeniser.error(`Trailing comma in ${listName}`); + } + break; + } + item.tokens.separator = tokeniser.consume(","); + items.push(item); + if (!item.tokens.separator) break; + } + return items; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function const_value(tokeniser) { + return tokeniser.consume("true", "false", "Infinity", "-Infinity", "NaN", "decimal", "integer"); +} + +/** + * @param {object} token + * @param {string} token.type + * @param {string} token.value + */ +function const_data({ type, value }) { + switch (type) { + case "true": + case "false": + return { type: "boolean", value: type === "true" }; + case "Infinity": + case "-Infinity": + return { type: "Infinity", negative: type.startsWith("-") }; + case "[": + return { type: "sequence", value: [] }; + case "{": + return { type: "dictionary" }; + case "decimal": + case "integer": + return { type: "number", value }; + case "string": + return { type: "string", value: value.slice(1, -1) }; + default: + return { type }; + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function primitive_type(tokeniser) { + function integer_type() { + const prefix = tokeniser.consume("unsigned"); + const base = tokeniser.consume("short", "long"); + if (base) { + const postfix = tokeniser.consume("long"); + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base, postfix } }); + } + if (prefix) tokeniser.error("Failed to parse integer type"); + } + + function decimal_type() { + const prefix = tokeniser.consume("unrestricted"); + const base = tokeniser.consume("float", "double"); + if (base) { + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { prefix, base } }); + } + if (prefix) tokeniser.error("Failed to parse float type"); + } + + const { source } = tokeniser; + const num_type = integer_type(tokeniser) || decimal_type(tokeniser); + if (num_type) return num_type; + const base = tokeniser.consume("boolean", "byte", "octet"); + if (base) { + return new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source, tokens: { base } }); + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function identifiers(tokeniser) { + const ids = list(tokeniser, { parser: _token_js__WEBPACK_IMPORTED_MODULE_2__["Token"].parser(tokeniser, "identifier"), listName: "identifier list" }); + if (!ids.length) { + tokeniser.error("Expected identifiers but none found"); + } + return ids; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function argument_list(tokeniser) { + return list(tokeniser, { parser: _argument_js__WEBPACK_IMPORTED_MODULE_1__["Argument"].parse, listName: "arguments list" }); +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function type_with_extended_attributes(tokeniser, typeName) { + const extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser); + const ret = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName); + if (ret) ret.extAttrs = extAttrs; + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function return_type(tokeniser, typeName) { + const typ = _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"].parse(tokeniser, typeName || "return-type"); + if (typ) { + return typ; + } + const voidToken = tokeniser.consume("void"); + if (voidToken) { + const ret = new _type_js__WEBPACK_IMPORTED_MODULE_0__["Type"]({ source: tokeniser.source, tokens: { base: voidToken } }); + ret.type = "return-type"; + return ret; + } +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function stringifier(tokeniser) { + const special = tokeniser.consume("stringifier"); + if (!special) return; + const member = _attribute_js__WEBPACK_IMPORTED_MODULE_5__["Attribute"].parse(tokeniser, { special }) || + _operation_js__WEBPACK_IMPORTED_MODULE_4__["Operation"].parse(tokeniser, { special }) || + tokeniser.error("Unterminated stringifier"); + return member; +} + +/** + * @param {string} str + */ +function getLastIndentation(str) { + const lines = str.split("\n"); + // the first line visually binds to the preceding token + if (lines.length) { + const match = lines[lines.length - 1].match(/^\s+/); + if (match) { + return match[0]; + } + } + return ""; +} + +/** + * @param {string} parentTrivia + */ +function getMemberIndentation(parentTrivia) { + const indentation = getLastIndentation(parentTrivia); + const indentCh = indentation.includes("\t") ? "\t" : " "; + return indentation + indentCh; +} + +/** + * @param {object} def + * @param {import("./extended-attributes.js").ExtendedAttributes} def.extAttrs + */ +function autofixAddExposedWindow(def) { + return () => { + if (def.extAttrs.length){ + const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_6__["Tokeniser"]("Exposed=Window,"); + const exposed = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["SimpleExtendedAttribute"].parse(tokeniser); + exposed.tokens.separator = tokeniser.consume(","); + const existing = def.extAttrs[0]; + if (!/^\s/.test(existing.tokens.name.trivia)) { + existing.tokens.name.trivia = ` ${existing.tokens.name.trivia}`; + } + def.extAttrs.unshift(exposed); + } else { + def.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(new _tokeniser_js__WEBPACK_IMPORTED_MODULE_6__["Tokeniser"]("[Exposed=Window]")); + const trivia = def.tokens.base.trivia; + def.extAttrs.tokens.open.trivia = trivia; + def.tokens.base.trivia = `\n${getLastIndentation(trivia)}`; } }; +} - if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { - module.exports = obj; - } else if (typeof define === 'function' && define.amd) { - define([], () => obj); - } else { - (self || window).WebIDL2 = obj; +/** + * Get the first syntax token for the given IDL object. + * @param {*} data + */ +function getFirstToken(data) { + if (data.extAttrs.length) { + return data.extAttrs.tokens.open; } -})(); + if (data.type === "operation") { + return getFirstToken(data.idlType); + } + const tokens = Object.values(data.tokens).sort((x, y) => x.index - y.index); + return tokens[0]; +} + + +/***/ }), +/* 5 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); +/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7); + + + + + + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function generic_type(tokeniser, typeName) { + const base = tokeniser.consume("FrozenArray", "Promise", "sequence", "record"); + if (!base) { + return; + } + const ret = new Type({ source: tokeniser.source, tokens: { base } }); + ret.tokens.open = tokeniser.consume("<") || tokeniser.error(`No opening bracket after ${base.type}`); + switch (base.type) { + case "Promise": { + if (tokeniser.probe("[")) tokeniser.error("Promise type cannot have extended attribute"); + const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser, typeName) || tokeniser.error("Missing Promise subtype"); + ret.subtype.push(subtype); + break; + } + case "sequence": + case "FrozenArray": { + const subtype = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error(`Missing ${base.type} subtype`); + ret.subtype.push(subtype); + break; + } + case "record": { + if (tokeniser.probe("[")) tokeniser.error("Record key cannot have extended attribute"); + const keyType = tokeniser.consume(..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]) || tokeniser.error(`Record key must be one of: ${_tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"].join(", ")}`); + const keyIdlType = new Type({ source: tokeniser.source, tokens: { base: keyType }}); + keyIdlType.tokens.separator = tokeniser.consume(",") || tokeniser.error("Missing comma after record key type"); + keyIdlType.type = typeName; + const valueType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, typeName) || tokeniser.error("Error parsing generic type record"); + ret.subtype.push(keyIdlType, valueType); + break; + } + } + if (!ret.idlType) tokeniser.error(`Error parsing generic type ${base.type}`); + ret.tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing closing bracket after ${base.type}`); + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function type_suffix(tokeniser, obj) { + const nullable = tokeniser.consume("?"); + if (nullable) { + obj.tokens.nullable = nullable; + } + if (tokeniser.probe("?")) tokeniser.error("Can't nullable more than once"); +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ +function single_type(tokeniser, typeName) { + let ret = generic_type(tokeniser, typeName) || Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["primitive_type"])(tokeniser); + if (!ret) { + const base = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_2__["stringTypes"]); + if (!base) { + return; + } + ret = new Type({ source: tokeniser.source, tokens: { base } }); + if (tokeniser.probe("<")) tokeniser.error(`Unsupported generic type ${base.value}`); + } + if (ret.generic === "Promise" && tokeniser.probe("?")) { + tokeniser.error("Promise type cannot be nullable"); + } + ret.type = typeName || null; + type_suffix(tokeniser, ret); + if (ret.nullable && ret.idlType === "any") tokeniser.error("Type `any` cannot be made nullable"); + return ret; +} + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} type + */ +function union_type(tokeniser, type) { + const tokens = {}; + tokens.open = tokeniser.consume("("); + if (!tokens.open) return; + const ret = new Type({ source: tokeniser.source, tokens }); + ret.type = type || null; + while (true) { + const typ = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error("No type after open parenthesis or 'or' in union type"); + if (typ.idlType === "any") tokeniser.error("Type `any` cannot be included in a union type"); + ret.subtype.push(typ); + const or = tokeniser.consume("or"); + if (or) { + typ.tokens.separator = or; + } + else break; + } + if (ret.idlType.length < 2) { + tokeniser.error("At least two types are expected in a union type but found less"); + } + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated union type"); + type_suffix(tokeniser, ret); + return ret; +} + +class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} typeName + */ + static parse(tokeniser, typeName) { + return single_type(tokeniser, typeName) || union_type(tokeniser, typeName); + } + + constructor({ source, tokens }) { + super({ source, tokens }); + Object.defineProperty(this, "subtype", { value: [] }); + this.extAttrs = []; + } + + get generic() { + if (this.subtype.length && this.tokens.base) { + return this.tokens.base.value; + } + return ""; + } + get nullable() { + return Boolean(this.tokens.nullable); + } + get union() { + return Boolean(this.subtype.length) && !this.tokens.base; + } + get idlType() { + if (this.subtype.length) { + return this.subtype; + } + // Adding prefixes/postfixes for "unrestricted float", etc. + const name = [ + this.tokens.prefix, + this.tokens.base, + this.tokens.postfix + ].filter(t => t).map(t => t.value).join(" "); + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name); + } + + *validate(defs) { + /* + * If a union is nullable, its subunions cannot include a dictionary + * If not, subunions may include dictionaries if each union is not nullable + */ + const typedef = !this.union && defs.unique.get(this.idlType); + const target = + this.union ? this : + (typedef && typedef.type === "typedef") ? typedef.idlType : + undefined; + if (target && this.nullable) { + // do not allow any dictionary + const reference = Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__["idlTypeIncludesDictionary"])(target, defs); + if (reference) { + const targetToken = (this.union ? reference : this).tokens.base; + const message = `Nullable union cannot include a dictionary type`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(targetToken, this, "no-nullable-union-dict", message); + } + } else { + // allow some dictionary + for (const subtype of this.subtype) { + yield* subtype.validate(defs); + } + } + } +} + + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Base", function() { return Base; }); +class Base { + constructor({ source, tokens }) { + Object.defineProperties(this, { + source: { value: source }, + tokens: { value: tokens } + }); + } + + toJSON() { + const json = { type: undefined, name: undefined, inheritance: undefined }; + let proto = this; + while (proto !== Object.prototype) { + const descMap = Object.getOwnPropertyDescriptors(proto); + for (const [key, value] of Object.entries(descMap)) { + if (value.enumerable || value.get) { + json[key] = this[key]; + } + } + proto = Object.getPrototypeOf(proto); + } + return json; + } +} + + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "idlTypeIncludesDictionary", function() { return idlTypeIncludesDictionary; }); +/** + * @param {*} idlType + * @param {*[]} defs + * @param {object} [options] + * @param {boolean} [options.useNullableInner] use when the input idlType is nullable and you want to use its inner type + * @return the type reference that ultimately includes dictionary. + */ +function idlTypeIncludesDictionary(idlType, defs, { useNullableInner } = {}) { + if (!idlType.union) { + const def = defs.unique.get(idlType.idlType); + if (!def) { + return; + } + if (def.type === "typedef") { + const { typedefIncludesDictionary} = defs.cache; + if (typedefIncludesDictionary.has(def)) { + // Note that this also halts when it met indeterminate state + // to prevent infinite recursion + return typedefIncludesDictionary.get(def); + } + defs.cache.typedefIncludesDictionary.set(def, undefined); // indeterminate state + const result = idlTypeIncludesDictionary(def.idlType, defs); + defs.cache.typedefIncludesDictionary.set(def, result); + if (result) { + return idlType; + } + } + if (def.type === "dictionary" && (useNullableInner || !idlType.nullable)) { + return idlType; + } + } + for (const subtype of idlType.subtype) { + const result = idlTypeIncludesDictionary(subtype, defs); + if (result) { + if (subtype.union) { + return result; + } + return subtype; + } + } +} + + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Argument", function() { return Argument; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3); +/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(7); + + + + + + + + +class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const start_position = tokeniser.position; + const tokens = {}; + const ret = new Argument({ source: tokeniser.source, tokens }); + ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser); + tokens.optional = tokeniser.consume("optional"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["type_with_extended_attributes"])(tokeniser, "argument-type"); + if (!ret.idlType) { + return tokeniser.unconsume(start_position); + } + if (!tokens.optional) { + tokens.variadic = tokeniser.consume("..."); + } + tokens.name = tokeniser.consume("identifier", ..._tokeniser_js__WEBPACK_IMPORTED_MODULE_4__["argumentNameKeywords"]); + if (!tokens.name) { + return tokeniser.unconsume(start_position); + } + ret.default = tokens.optional ? _default_js__WEBPACK_IMPORTED_MODULE_1__["Default"].parse(tokeniser) : null; + return ret; + } + + get type() { + return "argument"; + } + get optional() { + return !!this.tokens.optional; + } + get variadic() { + return !!this.tokens.variadic; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); + if (Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__["idlTypeIncludesDictionary"])(this.idlType, defs, { useNullableInner: true })) { + if (this.idlType.nullable) { + const message = `Dictionary arguments cannot be nullable.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.tokens.name, this, "no-nullable-dict-arg", message); + } else if (this.optional && !this.default) { + const message = `Optional dictionary arguments must have a default value of \`{}\`.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.tokens.name, this, "dict-arg-default", message, { + autofix: autofixOptionalDictionaryDefaultValue(this) + }); + } + } + } +} + +/** + * @param {Argument} arg + */ +function autofixOptionalDictionaryDefaultValue(arg) { + return () => { + arg.default = _default_js__WEBPACK_IMPORTED_MODULE_1__["Default"].parse(new _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__["Tokeniser"](" = {}")); + }; +} + + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Default", function() { return Default; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const assign = tokeniser.consume("="); + if (!assign) { + return null; + } + const def = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_value"])(tokeniser) || tokeniser.consume("string", "null", "[", "{") || tokeniser.error("No value for default"); + const expression = [def]; + if (def.type === "[") { + const close = tokeniser.consume("]") || tokeniser.error("Default sequence value must be empty"); + expression.push(close); + } else if (def.type === "{") { + const close = tokeniser.consume("}") || tokeniser.error("Default dictionary value must be empty"); + expression.push(close); + } + return new Default({ source: tokeniser.source, tokens: { assign }, expression }); + } + + constructor({ source, tokens, expression }) { + super({ source, tokens }); + Object.defineProperty(this, "expression", { value: expression }); + } + + get type() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).type; + } + get value() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).value; + } + get negative() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["const_data"])(this.expression[0]).negative; + } +} + + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleExtendedAttribute", function() { return SimpleExtendedAttribute; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExtendedAttributes", function() { return ExtendedAttributes; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); + + + + + +class ExtendedAttributeParameters extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = { assign: tokeniser.consume("=") }; + const ret = new ExtendedAttributeParameters({ source: tokeniser.source, tokens }); + if (tokens.assign) { + tokens.secondaryName = tokeniser.consume("identifier", "decimal", "integer", "string"); + } + tokens.open = tokeniser.consume("("); + if (tokens.open) { + ret.list = ret.rhsType === "identifier-list" ? + // [Exposed=(Window,Worker)] + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["identifiers"])(tokeniser) : + // [NamedConstructor=Audio(DOMString src)] or [Constructor(DOMString str)] + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unexpected token in extended attribute argument list"); + } else if (ret.hasRhs && !tokens.secondaryName) { + tokeniser.error("No right hand side to extended attribute assignment"); + } + return ret; + } + + get rhsType() { + return !this.tokens.assign ? null : + !this.tokens.secondaryName ? "identifier-list" : + this.tokens.secondaryName.type; + } +} + +class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const name = tokeniser.consume("identifier"); + if (name) { + return new SimpleExtendedAttribute({ + source: tokeniser.source, + tokens: { name }, + params: ExtendedAttributeParameters.parse(tokeniser) + }); + } + } + + constructor({ source, tokens, params }) { + super({ source, tokens }); + Object.defineProperty(this, "params", { value: params }); + } + + get type() { + return "extended-attribute"; + } + get name() { + return this.tokens.name.value; + } + get rhs() { + const { rhsType: type, tokens, list } = this.params; + if (!type) { + return null; + } + const value = type === "identifier-list" ? list : tokens.secondaryName.value; + return { type, value }; + } + get arguments() { + const { rhsType, list } = this.params; + if (!list || rhsType === "identifier-list") { + return []; + } + return list; + } + + *validate(defs) { + if (this.name === "NoInterfaceObject") { + const message = `\`[NoInterfaceObject]\` extended attribute is an \ +undesirable feature that may be removed from Web IDL in the future. Refer to the \ +[relevant upstream PR](https://github.com/heycam/webidl/pull/609) for more \ +information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.tokens.name, this, "no-nointerfaceobject", message, { level: "warning" }); + } + for (const arg of this.arguments) { + yield* arg.validate(defs); + } + } +} + +// Note: we parse something simpler than the official syntax. It's all that ever +// seems to be used +class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["ArrayBase"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + tokens.open = tokeniser.consume("["); + if (!tokens.open) return new ExtendedAttributes({}); + const ret = new ExtendedAttributes({ source: tokeniser.source, tokens }); + ret.push(...Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["list"])(tokeniser, { + parser: SimpleExtendedAttribute.parse, + listName: "extended attribute" + })); + tokens.close = tokeniser.consume("]") || tokeniser.error("Unexpected closing token of extended attribute"); + if (!ret.length) { + tokeniser.error("Found an empty extended attribute"); + } + if (tokeniser.probe("[")) { + tokeniser.error("Illegal double extended attribute lists, consider merging them"); + } + return ret; + } + + *validate(defs) { + for (const extAttr of this) { + yield* extAttr.validate(defs); + } + } +} + + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayBase", function() { return ArrayBase; }); +class ArrayBase extends Array { + constructor({ source, tokens }) { + super(); + Object.defineProperties(this, { + source: { value: source }, + tokens: { value: tokens } + }); + } +} + + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); + + +class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + * @param {string} type + */ + static parser(tokeniser, type) { + return () => { + const value = tokeniser.consume(type); + if (value) { + return new Token({ source: tokeniser.source, tokens: { value } }); + } + }; + } + + get value() { + return this.tokens.value.value; + } +} + + +/***/ }), +/* 13 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Operation", function() { return Operation; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); + + + + +class Operation extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser, { special, regular } = {}) { + const tokens = { special }; + const ret = new Operation({ source: tokeniser.source, tokens }); + if (special && special.value === "stringifier") { + tokens.termination = tokeniser.consume(";"); + if (tokens.termination) { + ret.arguments = []; + return ret; + } + } + if (!special && !regular) { + tokens.special = tokeniser.consume("getter", "setter", "deleter"); + } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Missing return type"); + tokens.name = tokeniser.consume("identifier", "includes"); + tokens.open = tokeniser.consume("(") || tokeniser.error("Invalid operation"); + ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated operation"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated operation, expected `;`"); + return ret; + } + + get type() { + return "operation"; + } + get name() { + const { name } = this.tokens; + if (!name) { + return ""; + } + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name.value); + } + get special() { + if (!this.tokens.special) { + return ""; + } + return this.tokens.special.value; + } + + *validate(defs) { + if (!this.name && ["", "static"].includes(this.special)) { + const message = `Regular or static operations must have both a return type and an identifier.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_2__["validationError"])(this.tokens.open, this, "incomplete-op", message); + } + if (this.idlType) { + yield* this.idlType.validate(defs); + } + for (const argument of this.arguments) { + yield* argument.validate(defs); + } + } +} + + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Attribute", function() { return Attribute; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class Attribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser, { special, noInherit = false, readonly = false } = {}) { + const start_position = tokeniser.position; + const tokens = { special }; + const ret = new Attribute({ source: tokeniser.source, tokens }); + if (!special && !noInherit) { + tokens.special = tokeniser.consume("inherit"); + } + if (ret.special === "inherit" && tokeniser.probe("readonly")) { + tokeniser.error("Inherited attributes cannot be read-only"); + } + tokens.readonly = tokeniser.consume("readonly"); + if (readonly && !tokens.readonly && tokeniser.probe("attribute")) { + tokeniser.error("Attributes must be readonly in this context"); + } + tokens.base = tokeniser.consume("attribute"); + if (!tokens.base) { + tokeniser.unconsume(start_position); + return; + } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "attribute-type") || tokeniser.error("Attribute lacks a type"); + switch (ret.idlType.generic) { + case "sequence": + case "record": tokeniser.error(`Attributes cannot accept ${ret.idlType.generic} types`); + } + tokens.name = tokeniser.consume("identifier", "async", "required") || tokeniser.error("Attribute lacks a name"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated attribute, expected `;`"); + return ret; + } + + get type() { + return "attribute"; + } + get special() { + if (!this.tokens.special) { + return ""; + } + return this.tokens.special.value; + } + get readonly() { + return !!this.tokens.readonly; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); + } +} + + +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Enum", function() { return Enum; }); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); +/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6); + + + + +class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const value = tokeniser.consume("string"); + if (value) { + return new EnumValue({ source: tokeniser.source, tokens: { value } }); + } + } + + get type() { + return "enum-value"; + } + get value() { + return super.value.slice(1, -1); + } +} + +class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + tokens.base = tokeniser.consume("enum"); + if (!tokens.base) { + return; + } + tokens.name = tokeniser.consume("identifier") || tokeniser.error("No name for enum"); + const ret = tokeniser.current = new Enum({ source: tokeniser.source, tokens }); + tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum"); + ret.values = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["list"])(tokeniser, { + parser: EnumValue.parse, + allowDangler: true, + listName: "enumeration" + }); + if (tokeniser.probe("string")) { + tokeniser.error("No comma between enum values"); + } + tokens.close = tokeniser.consume("}") || tokeniser.error("Unexpected value in enum"); + if (!ret.values.length) { + tokeniser.error("No value in enum"); + } + tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum"); + return ret; + } + + get type() { + return "enum"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value); + } +} + + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Includes", function() { return Includes; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const target = tokeniser.consume("identifier"); + if (!target) { + return; + } + const tokens = { target }; + tokens.includes = tokeniser.consume("includes"); + if (!tokens.includes) { + tokeniser.unconsume(target.index); + return; + } + tokens.mixin = tokeniser.consume("identifier") || tokeniser.error("Incomplete includes statement"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("No terminating ; for includes statement"); + return new Includes({ source: tokeniser.source, tokens }); + } + + get type() { + return "includes"; + } + get target() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.target.value); + } + get includes() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.mixin.value); + } +} + + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Typedef", function() { return Typedef; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class Typedef extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + const ret = new Typedef({ source: tokeniser.source, tokens }); + tokens.base = tokeniser.consume("typedef"); + if (!tokens.base) { + return; + } + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "typedef-type") || tokeniser.error("Typedef lacks a type"); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Typedef lacks a name"); + tokeniser.current = ret; + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated typedef, expected `;`"); + return ret; + } + + get type() { + return "typedef"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); + } +} + + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackFunction", function() { return CallbackFunction; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class CallbackFunction extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser, base) { + const tokens = { base }; + const ret = new CallbackFunction({ source: tokeniser.source, tokens }); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Callback lacks a name"); + tokeniser.current = ret; + tokens.assign = tokeniser.consume("=") || tokeniser.error("Callback lacks an assignment"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Callback lacks a return type"); + tokens.open = tokeniser.consume("(") || tokeniser.error("Callback lacks parentheses for arguments"); + ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated callback"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated callback, expected `;`"); + return ret; + } + + get type() { + return "callback"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + + *validate(defs) { + yield* this.idlType.validate(defs); + } +} + + +/***/ }), +/* 19 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interface", function() { return Interface; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(21); +/* harmony import */ var _iterable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(4); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3); +/* harmony import */ var _validators_interface_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(23); +/* harmony import */ var _constructor_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(24); +/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(2); + + + + + + + + + + + +/** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ +function static_member(tokeniser) { + const special = tokeniser.consume("static"); + if (!special) return; + const member = _attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse(tokeniser, { special }) || + _operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse(tokeniser, { special }) || + tokeniser.error("No body in static member"); + return member; +} + +class Interface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, base, { partial = null } = {}) { + const tokens = { partial, base }; + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Interface({ source: tokeniser.source, tokens }), { + type: "interface", + inheritable: !partial, + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_3__["Constant"].parse], + [_constructor_js__WEBPACK_IMPORTED_MODULE_8__["Constructor"].parse], + [static_member], + [_helpers_js__WEBPACK_IMPORTED_MODULE_5__["stringifier"]], + [_iterable_js__WEBPACK_IMPORTED_MODULE_4__["IterableLike"].parse], + [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse], + [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse] + ] + }); + } + + get type() { + return "interface"; + } + + *validate(defs) { + yield* this.extAttrs.validate(defs); + if ( + !this.partial && + this.extAttrs.every(extAttr => extAttr.name !== "Exposed") && + this.extAttrs.every(extAttr => extAttr.name !== "NoInterfaceObject") + ) { + const message = `Interfaces must have \`[Exposed]\` extended attribute. \ +To fix, add, for example, \`[Exposed=Window]\`. Please also consider carefully \ +if your interface should also be exposed in a Worker scope. Refer to the \ +[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ +for more information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_6__["validationError"])(this.tokens.name, this, "require-exposed", message, { + autofix: Object(_helpers_js__WEBPACK_IMPORTED_MODULE_5__["autofixAddExposedWindow"])(this) + }); + } + const constructors = this.extAttrs.filter(extAttr => extAttr.name === "Constructor"); + for (const constructor of constructors) { + const message = `Constructors should now be represented as a \`constructor()\` operation on the interface \ +instead of \`[Constructor]\` extended attribute. Refer to the \ +[WebIDL spec section on constructor operations](https://heycam.github.io/webidl/#idl-constructors) \ +for more information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_6__["validationError"])(constructor.tokens.name, this, "constructor-member", message, { + autofix: autofixConstructor(this, constructor) + }); + } + + yield* super.validate(defs); + if (!this.partial) { + yield* Object(_validators_interface_js__WEBPACK_IMPORTED_MODULE_7__["checkInterfaceMemberDuplication"])(defs, this); + } + } +} + +function autofixConstructor(interfaceDef, constructorExtAttr) { + return () => { + const indentation = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_5__["getLastIndentation"])(interfaceDef.extAttrs.tokens.open.trivia); + const memberIndent = interfaceDef.members.length ? + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_5__["getLastIndentation"])(Object(_helpers_js__WEBPACK_IMPORTED_MODULE_5__["getFirstToken"])(interfaceDef.members[0]).trivia) : + Object(_helpers_js__WEBPACK_IMPORTED_MODULE_5__["getMemberIndentation"])(indentation); + const constructorOp = _constructor_js__WEBPACK_IMPORTED_MODULE_8__["Constructor"].parse(new _tokeniser_js__WEBPACK_IMPORTED_MODULE_9__["Tokeniser"](`\n${memberIndent}constructor();`)); + constructorOp.extAttrs = []; + constructorOp.arguments = constructorExtAttr.arguments; + + const existingIndex = interfaceDef.members.findIndex(m => m.type === "constructor"); + interfaceDef.members.splice(existingIndex + 1, 0, constructorOp); + + const { close } = interfaceDef.tokens; + if (!close.trivia.includes("\n")) { + close.trivia += `\n${indentation}`; + } + + const { extAttrs } = interfaceDef; + const index = extAttrs.indexOf(constructorExtAttr); + const removed = extAttrs.splice(index, 1); + if (!extAttrs.length) { + extAttrs.tokens.open = extAttrs.tokens.close = undefined; + } else if (extAttrs.length === index) { + extAttrs[index - 1].tokens.separator = undefined; + } else if (!extAttrs[index].tokens.name.trivia.trim()) { + extAttrs[index].tokens.name.trivia = removed[0].tokens.name.trivia; + } + }; +} + + +/***/ }), +/* 20 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); + + + + +/** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ +function inheritance(tokeniser) { + const colon = tokeniser.consume(":"); + if (!colon) { + return {}; + } + const inheritance = tokeniser.consume("identifier") || tokeniser.error("Inheritance lacks a type"); + return { colon, inheritance }; +} + +class Container extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + * @param {*} instance + * @param {*} args + */ + static parse(tokeniser, instance, { type, inheritable, allowedMembers }) { + const { tokens } = instance; + tokens.name = tokeniser.consume("identifier") || tokeniser.error(`Missing name in ${instance.type}`); + tokeniser.current = instance; + if (inheritable) { + Object.assign(tokens, inheritance(tokeniser)); + } + tokens.open = tokeniser.consume("{") || tokeniser.error(`Bodyless ${type}`); + instance.members = []; + while (true) { + tokens.close = tokeniser.consume("}"); + if (tokens.close) { + tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type}`); + return instance; + } + const ea = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__["ExtendedAttributes"].parse(tokeniser); + let mem; + for (const [parser, ...args] of allowedMembers) { + mem = parser(tokeniser, ...args); + if (mem) { + break; + } + } + if (!mem) { + tokeniser.error("Unknown member"); + } + mem.extAttrs = ea; + instance.members.push(mem); + } + } + + get partial() { + return !!this.tokens.partial; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.name.value); + } + get inheritance() { + if (!this.tokens.inheritance) { + return null; + } + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.inheritance.value); + } + + *validate(defs) { + for (const member of this.members) { + if (member.validate) { + yield* member.validate(defs); + } + } + } + } + + +/***/ }), +/* 21 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Constant", function() { return Constant; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); + + + + +class Constant extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + tokens.base = tokeniser.consume("const"); + if (!tokens.base) { + return; + } + let idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["primitive_type"])(tokeniser); + if (!idlType) { + const base = tokeniser.consume("identifier") || tokeniser.error("Const lacks a type"); + idlType = new _type_js__WEBPACK_IMPORTED_MODULE_1__["Type"]({ source: tokeniser.source, tokens: { base } }); + } + if (tokeniser.probe("?")) { + tokeniser.error("Unexpected nullable constant type"); + } + idlType.type = "const-type"; + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Const lacks a name"); + tokens.assign = tokeniser.consume("=") || tokeniser.error("Const lacks value assignment"); + tokens.value = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_value"])(tokeniser) || tokeniser.error("Const lacks a value"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated const, expected `;`"); + const ret = new Constant({ source: tokeniser.source, tokens }); + ret.idlType = idlType; + return ret; + } + + get type() { + return "const"; + } + get name() { + return unescape(this.tokens.name.value); + } + get value() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_data"])(this.tokens.value); + } +} + + +/***/ }), +/* 22 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IterableLike", function() { return IterableLike; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class IterableLike extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser.js").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const start_position = tokeniser.position; + const tokens = {}; + const ret = new IterableLike({ source: tokeniser.source, tokens }); + tokens.readonly = tokeniser.consume("readonly"); + if (!tokens.readonly) { + tokens.async = tokeniser.consume("async"); + } + tokens.base = + tokens.readonly ? tokeniser.consume("maplike", "setlike") : + tokens.async ? tokeniser.consume("iterable") : + tokeniser.consume("iterable", "maplike", "setlike"); + if (!tokens.base) { + tokeniser.unconsume(start_position); + return; + } + + const { type } = ret; + const secondTypeRequired = type === "maplike" || ret.async; + const secondTypeAllowed = secondTypeRequired || type === "iterable"; + + tokens.open = tokeniser.consume("<") || tokeniser.error(`Missing less-than sign \`<\` in ${type} declaration`); + const first = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error(`Missing a type argument in ${type} declaration`); + ret.idlType = [first]; + if (secondTypeAllowed) { + first.tokens.separator = tokeniser.consume(","); + if (first.tokens.separator) { + ret.idlType.push(Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser)); + } + else if (secondTypeRequired) { + tokeniser.error(`Missing second type argument in ${type} declaration`); + } + } + tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing greater-than sign \`>\` in ${type} declaration`); + tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type} declaration`); + + return ret; + } + + get type() { + return this.tokens.base.value; + } + get readonly() { + return !!this.tokens.readonly; + } + get async() { + return !!this.tokens.async; + } +} + + +/***/ }), +/* 23 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "checkInterfaceMemberDuplication", function() { return checkInterfaceMemberDuplication; }); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); + + +function* checkInterfaceMemberDuplication(defs, i) { + const opNames = new Set(getOperations(i).map(op => op.name)); + const partials = defs.partials.get(i.name) || []; + const mixins = defs.mixinMap.get(i.name) || []; + for (const ext of [...partials, ...mixins]) { + const additions = getOperations(ext); + yield* forEachExtension(additions, opNames, ext, i); + for (const addition of additions) { + opNames.add(addition.name); + } + } + + function* forEachExtension(additions, existings, ext, base) { + for (const addition of additions) { + const { name } = addition; + if (name && existings.has(name)) { + const message = `The operation "${name}" has already been defined for the base interface "${base.name}" either in itself or in a mixin`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(addition.tokens.name, ext, "no-cross-overload", message); + } + } + } + + function getOperations(i) { + return i.members + .filter(({type}) => type === "operation"); + } +} + + +/***/ }), +/* 24 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Constructor", function() { return Constructor; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); + + + +class Constructor extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const base = tokeniser.consume("constructor"); + if (!base) { + return; + } + const tokens = { base }; + tokens.open = tokeniser.consume("(") || tokeniser.error("No argument list in constructor"); + const args = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser); + tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated constructor"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after constructor"); + const ret = new Constructor({ tokens }); + ret.arguments = args; + return ret; + } + + get type() { + return "constructor"; + } + + *validate(defs) { + if (this.idlType) { + yield* this.idlType.validate(defs); + } + for (const argument of this.arguments) { + yield* argument.validate(defs); + } + } +} + + +/***/ }), +/* 25 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Mixin", function() { return Mixin; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4); + + + + + + +class Mixin extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, base, { partial } = {}) { + const tokens = { partial, base }; + tokens.mixin = tokeniser.consume("mixin"); + if (!tokens.mixin) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Mixin({ source: tokeniser.source, tokens }), { + type: "interface mixin", + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_1__["Constant"].parse], + [_helpers_js__WEBPACK_IMPORTED_MODULE_4__["stringifier"]], + [_attribute_js__WEBPACK_IMPORTED_MODULE_2__["Attribute"].parse, { noInherit: true }], + [_operation_js__WEBPACK_IMPORTED_MODULE_3__["Operation"].parse, { regular: true }] + ] + }); + } + + get type() { + return "interface mixin"; + } +} + + +/***/ }), +/* 26 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Dictionary", function() { return Dictionary; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _field_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); + + + +class Dictionary extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, { partial } = {}) { + const tokens = { partial }; + tokens.base = tokeniser.consume("dictionary"); + if (!tokens.base) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Dictionary({ source: tokeniser.source, tokens }), { + type: "dictionary", + inheritable: !partial, + allowedMembers: [ + [_field_js__WEBPACK_IMPORTED_MODULE_1__["Field"].parse], + ] + }); + } + + get type() { + return "dictionary"; + } +} + + +/***/ }), +/* 27 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Field", function() { return Field; }); +/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); +/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); +/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9); + + + + + +class Field extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser) { + const tokens = {}; + const ret = new Field({ source: tokeniser.source, tokens }); + ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser); + tokens.required = tokeniser.consume("required"); + ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "dictionary-type") || tokeniser.error("Dictionary member lacks a type"); + tokens.name = tokeniser.consume("identifier") || tokeniser.error("Dictionary member lacks a name"); + ret.default = _default_js__WEBPACK_IMPORTED_MODULE_3__["Default"].parse(tokeniser); + if (tokens.required && ret.default) tokeniser.error("Required member must not have a default"); + tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated dictionary member, expected `;`"); + return ret; + } + + get type() { + return "field"; + } + get name() { + return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value); + } + get required() { + return !!this.tokens.required; + } + + *validate(defs) { + yield* this.idlType.validate(defs); + } +} + + +/***/ }), +/* 28 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Namespace", function() { return Namespace; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3); +/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4); + + + + + + +class Namespace extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, { partial } = {}) { + const tokens = { partial }; + tokens.base = tokeniser.consume("namespace"); + if (!tokens.base) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Namespace({ source: tokeniser.source, tokens }), { + type: "namespace", + allowedMembers: [ + [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse, { noInherit: true, readonly: true }], + [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse, { regular: true }] + ] + }); + } + + get type() { + return "namespace"; + } + + *validate(defs) { + if (!this.partial && this.extAttrs.every(extAttr => extAttr.name !== "Exposed")) { + const message = `Namespaces must have [Exposed] extended attribute. \ +To fix, add, for example, [Exposed=Window]. Please also consider carefully \ +if your namespace should also be exposed in a Worker scope. Refer to the \ +[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \ +for more information.`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.tokens.name, this, "require-exposed", message, { + autofix: Object(_helpers_js__WEBPACK_IMPORTED_MODULE_4__["autofixAddExposedWindow"])(this) + }); + } + yield* super.validate(defs); + } +} + + +/***/ }), +/* 29 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackInterface", function() { return CallbackInterface; }); +/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20); +/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13); +/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); + + + + + +class CallbackInterface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] { + /** + * @param {import("../tokeniser").Tokeniser} tokeniser + */ + static parse(tokeniser, callback, { partial = null } = {}) { + const tokens = { callback }; + tokens.base = tokeniser.consume("interface"); + if (!tokens.base) { + return; + } + return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new CallbackInterface({ source: tokeniser.source, tokens }), { + type: "callback interface", + inheritable: !partial, + allowedMembers: [ + [_constant_js__WEBPACK_IMPORTED_MODULE_2__["Constant"].parse], + [_operation_js__WEBPACK_IMPORTED_MODULE_1__["Operation"].parse, { regular: true }] + ] + }); + } + + get type() { + return "callback interface"; + } +} + + +/***/ }), +/* 30 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "write", function() { return write; }); + + +function noop(arg) { + return arg; +} + +const templates = { + wrap: items => items.join(""), + trivia: noop, + name: noop, + reference: noop, + type: noop, + generic: noop, + nameless: noop, + inheritance: noop, + definition: noop, + extendedAttribute: noop, + extendedAttributeReference: noop +}; + +function write(ast, { templates: ts = templates } = {}) { + ts = Object.assign({}, templates, ts); + + function reference(raw, { unescaped, context }) { + if (!unescaped) { + unescaped = raw.startsWith("_") ? raw.slice(1) : raw; + } + return ts.reference(raw, unescaped, context); + } + + function token(t, wrapper = noop, ...args) { + if (!t) { + return ""; + } + const value = wrapper(t.value, ...args); + return ts.wrap([ts.trivia(t.trivia), value]); + } + + function reference_token(t, context) { + return token(t, reference, { context }); + } + + function name_token(t, arg) { + return token(t, ts.name, arg); + } + + function type_body(it) { + if (it.union || it.generic) { + return ts.wrap([ + token(it.tokens.base, ts.generic), + token(it.tokens.open), + ...it.subtype.map(type), + token(it.tokens.close) + ]); + } + const firstToken = it.tokens.prefix || it.tokens.base; + const prefix = it.tokens.prefix ? [ + it.tokens.prefix.value, + ts.trivia(it.tokens.base.trivia) + ] : []; + const ref = reference(ts.wrap([ + ...prefix, + it.tokens.base.value, + token(it.tokens.postfix) + ]), { unescaped: it.idlType, context: it }); + return ts.wrap([ts.trivia(firstToken.trivia), ref]); + } + function type(it) { + return ts.wrap([ + extended_attributes(it.extAttrs), + type_body(it), + token(it.tokens.nullable), + token(it.tokens.separator) + ]); + } + function default_(def) { + if (!def) { + return ""; + } + return ts.wrap([ + token(def.tokens.assign), + ...def.expression.map(t => token(t)) + ]); + } + function argument(arg) { + return ts.wrap([ + extended_attributes(arg.extAttrs), + token(arg.tokens.optional), + ts.type(type(arg.idlType)), + token(arg.tokens.variadic), + name_token(arg.tokens.name, { data: arg }), + default_(arg.default), + token(arg.tokens.separator) + ]); + } + function identifier(id, context) { + return ts.wrap([ + reference_token(id.tokens.value, context), + token(id.tokens.separator) + ]); + } + function make_ext_at(it) { + const { rhsType } = it.params; + return ts.wrap([ + ts.trivia(it.tokens.name.trivia), + ts.extendedAttribute(ts.wrap([ + ts.extendedAttributeReference(it.name), + token(it.params.tokens.assign), + reference_token(it.params.tokens.secondaryName, it), + token(it.params.tokens.open), + ...!it.params.list ? [] : + it.params.list.map( + rhsType === "identifier-list" ? id => identifier(id, it) : argument + ), + token(it.params.tokens.close) + ])), + token(it.tokens.separator) + ]); + } + function extended_attributes(eats) { + if (!eats.length) return ""; + return ts.wrap([ + token(eats.tokens.open), + ...eats.map(make_ext_at), + token(eats.tokens.close) + ]); + } + + function operation(it, parent) { + const body = it.idlType ? [ + ts.type(type(it.idlType)), + name_token(it.tokens.name, { data: it, parent }), + token(it.tokens.open), + ts.wrap(it.arguments.map(argument)), + token(it.tokens.close), + ] : []; + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + it.tokens.name ? token(it.tokens.special) : token(it.tokens.special, ts.nameless, { data: it, parent }), + ...body, + token(it.tokens.termination) + ]), { data: it, parent }); + } + + function attribute(it, parent) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.special), + token(it.tokens.readonly), + token(it.tokens.base), + ts.type(type(it.idlType)), + name_token(it.tokens.name, { data: it, parent }), + token(it.tokens.termination) + ]), { data: it, parent }); + } + + function constructor(it, parent) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.base, ts.nameless, { data: it, parent }), + token(it.tokens.open), + ts.wrap(it.arguments.map(argument)), + token(it.tokens.close), + token(it.tokens.termination) + ]), { data: it, parent }); + } + + function inheritance(inh) { + if (!inh.tokens.inheritance) { + return ""; + } + return ts.wrap([ + token(inh.tokens.colon), + ts.trivia(inh.tokens.inheritance.trivia), + ts.inheritance(reference(inh.tokens.inheritance.value, { context: inh })) + ]); + } + + function container(it) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.callback), + token(it.tokens.partial), + token(it.tokens.base), + token(it.tokens.mixin), + name_token(it.tokens.name, { data: it }), + inheritance(it), + token(it.tokens.open), + iterate(it.members, it), + token(it.tokens.close), + token(it.tokens.termination) + ]), { data: it }); + } + + function field(it, parent) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.required), + ts.type(type(it.idlType)), + name_token(it.tokens.name, { data: it, parent }), + default_(it.default), + token(it.tokens.termination) + ]), { data: it, parent }); + } + function const_(it, parent) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.base), + ts.type(type(it.idlType)), + name_token(it.tokens.name, { data: it, parent }), + token(it.tokens.assign), + token(it.tokens.value), + token(it.tokens.termination) + ]), { data: it, parent }); + } + function typedef(it) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.base), + ts.type(type(it.idlType)), + name_token(it.tokens.name, { data: it }), + token(it.tokens.termination) + ]), { data: it }); + } + function includes(it) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + reference_token(it.tokens.target, it), + token(it.tokens.includes), + reference_token(it.tokens.mixin, it), + token(it.tokens.termination) + ]), { data: it }); + } + function callback(it) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.base), + name_token(it.tokens.name, { data: it }), + token(it.tokens.assign), + ts.type(type(it.idlType)), + token(it.tokens.open), + ...it.arguments.map(argument), + token(it.tokens.close), + token(it.tokens.termination), + ]), { data: it }); + } + function enum_(it) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.base), + name_token(it.tokens.name, { data: it }), + token(it.tokens.open), + iterate(it.values, it), + token(it.tokens.close), + token(it.tokens.termination) + ]), { data: it }); + } + function enum_value(v, parent) { + return ts.wrap([ + ts.trivia(v.tokens.value.trivia), + ts.definition( + ts.wrap(['"', ts.name(v.value, { data: v, parent }), '"']), + { data: v, parent } + ), + token(v.tokens.separator) + ]); + } + function iterable_like(it, parent) { + return ts.definition(ts.wrap([ + extended_attributes(it.extAttrs), + token(it.tokens.readonly), + token(it.tokens.async), + token(it.tokens.base, ts.generic), + token(it.tokens.open), + ts.wrap(it.idlType.map(type)), + token(it.tokens.close), + token(it.tokens.termination) + ]), { data: it, parent }); + } + function eof(it) { + return ts.trivia(it.trivia); + } + + const table = { + interface: container, + "interface mixin": container, + namespace: container, + operation, + attribute, + constructor, + dictionary: container, + field, + const: const_, + typedef, + includes, + callback, + enum: enum_, + "enum-value": enum_value, + iterable: iterable_like, + maplike: iterable_like, + setlike: iterable_like, + "callback interface": container, + eof + }; + function dispatch(it, parent) { + const dispatcher = table[it.type]; + if (!dispatcher) { + throw new Error(`Type "${it.type}" is unsupported`); + } + return table[it.type](it, parent); + } + function iterate(things, parent) { + if (!things) return; + const results = things.map(thing => dispatch(thing, parent)); + return ts.wrap(results); + } + return iterate(ast); +} + + +/***/ }), +/* 31 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return validate; }); +/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); + + + + +function getMixinMap(all, unique) { + const map = new Map(); + const includes = all.filter(def => def.type === "includes"); + for (const include of includes) { + const mixin = unique.get(include.includes); + if (!mixin) { + continue; + } + const array = map.get(include.target); + if (array) { + array.push(mixin); + } else { + map.set(include.target, [mixin]); + } + } + return map; +} + +function groupDefinitions(all) { + const unique = new Map(); + const duplicates = new Set(); + const partials = new Map(); + for (const def of all) { + if (def.partial) { + const array = partials.get(def.name); + if (array) { + array.push(def); + } else { + partials.set(def.name, [def]); + } + continue; + } + if (!def.name) { + continue; + } + if (!unique.has(def.name)) { + unique.set(def.name, def); + } else { + duplicates.add(def); + } + } + return { + all, + unique, + partials, + duplicates, + mixinMap: getMixinMap(all, unique), + cache: { + typedefIncludesDictionary: new WeakMap() + }, + }; +} + +function* checkDuplicatedNames({ unique, duplicates }) { + for (const dup of duplicates) { + const { name } = dup; + const message = `The name "${name}" of type "${unique.get(name).type}" was already seen`; + yield Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(dup.tokens.name, dup, "no-duplicate", message); + } +} + +function* validateIterable(ast) { + const defs = groupDefinitions(ast); + for (const def of defs.all) { + if (def.validate) { + yield* def.validate(defs); + } + } + yield* checkDuplicatedNames(defs); +} + +// Remove this once all of our support targets expose `.flat()` by default +function flatten(array) { + if (array.flat) { + return array.flat(); + } + return [].concat(...array); +} + +/** + * @param {*} ast AST or array of ASTs + */ +function validate(ast) { + return [...validateIterable(flatten(ast))]; +} + + +/***/ }) +/******/ ]); +}); +//# sourceMappingURL=webidl2.js.map
diff --git a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt index ff25b12b..9d01491 100644 --- a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt +++ b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -webkit-app-region: none --webkit-appearance: none -webkit-border-horizontal-spacing: 0px -webkit-border-image: none -webkit-border-vertical-spacing: 0px @@ -63,6 +62,7 @@ animation-name: none animation-play-state: running animation-timing-function: ease +appearance: none backdrop-filter: none backface-visibility: visible background-attachment: scroll
diff --git a/third_party/blink/web_tests/svg/custom/calc-expression-with-zoom.html b/third_party/blink/web_tests/svg/custom/calc-expression-with-zoom.html index 9a76d709..d983f5d 100644 --- a/third_party/blink/web_tests/svg/custom/calc-expression-with-zoom.html +++ b/third_party/blink/web_tests/svg/custom/calc-expression-with-zoom.html
@@ -3,6 +3,6 @@ body { zoom: 200%; } </style> <svg id="svg" width="500" height="500" viewBox='0 0 1000 1000'> - <rect width='calc(50px + 50)' height='100' fill='green'/> + <rect width='calc(50px + 50px)' height='100' fill='green'/> <rect x='110' width='calc(50 + 50)' height='100' fill='green'/> </svg>
diff --git a/third_party/blink/web_tests/svg/custom/rect-calc-corner-radii.svg b/third_party/blink/web_tests/svg/custom/rect-calc-corner-radii.svg index fe98961..55e9c79 100644 --- a/third_party/blink/web_tests/svg/custom/rect-calc-corner-radii.svg +++ b/third_party/blink/web_tests/svg/custom/rect-calc-corner-radii.svg
@@ -1,5 +1,5 @@ <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"> <rect x="50" y="50" width="400" height="400" rx="calc(-50)" ry="calc(-50)" fill="#00ff00" /> - <rect x="150" y="100" width="200" height="300" rx="calc(20% - 50)" ry="50" fill="#0000ff" /> + <rect x="150" y="100" width="200" height="300" rx="calc(20% - 50px)" ry="50" fill="#0000ff" /> <rect x="200" y="150" width="100" height="200" rx="50" ry="-100" fill="#ff0000" /> </svg>
diff --git a/third_party/blink/web_tests/svg/dom/SVGLength-calc-in-attr.html b/third_party/blink/web_tests/svg/dom/SVGLength-calc-in-attr.html index 3d4a704..7b718975 100644 --- a/third_party/blink/web_tests/svg/dom/SVGLength-calc-in-attr.html +++ b/third_party/blink/web_tests/svg/dom/SVGLength-calc-in-attr.html
@@ -82,10 +82,10 @@ assert_calc_expression("calc(10mm + 10mm)", (20 * cssPixelsPerMillimeter)); assert_calc_expression("calc(20mm)", (20 * cssPixelsPerMillimeter)); assert_calc_expression("calc(10 + 10)", 20); - assert_calc_expression("calc(10mm + 10)", (10 * cssPixelsPerMillimeter) + 10); - assert_calc_expression("calc(10% + 10)", (10 * viewportWidthPercent()) + 10); - assert_calc_expression("calc(1cm + 2in + 1cm + 2)", (2 * cssPixelsPerInch) + (2 * cssPixelsPerCentimeter) + 2); - assert_calc_expression("calc(1cm + 2 + 1cm + 2in)", (2 * cssPixelsPerInch) + (2 * cssPixelsPerCentimeter) + 2); - assert_calc_expression("calc(10% + 10 + 2% + 10pc)", (12 * viewportWidthPercent()) + 10 + (10 * cssPixelsPerPica)); + assert_calc_expression("calc(10mm + 10px)", (10 * cssPixelsPerMillimeter) + 10); + assert_calc_expression("calc(10% + 10px)", (10 * viewportWidthPercent()) + 10); + assert_calc_expression("calc(1cm + 2in + 1cm + 2px)", (2 * cssPixelsPerInch) + (2 * cssPixelsPerCentimeter) + 2); + assert_calc_expression("calc(1cm + 2px + 1cm + 2in)", (2 * cssPixelsPerInch) + (2 * cssPixelsPerCentimeter) + 2); + assert_calc_expression("calc(10% + 10px + 2% + 10pc)", (12 * viewportWidthPercent()) + 10 + (10 * cssPixelsPerPica)); }, "Tests calc() on presentation and non-presentation attr in svgLength"); </script>
diff --git a/third_party/blink/web_tests/virtual/force-defer-script/defer-script/async-script-expected.txt b/third_party/blink/web_tests/virtual/force-defer-script/defer-script/async-script-expected.txt index 794f008..9160632 100644 --- a/third_party/blink/web_tests/virtual/force-defer-script/defer-script/async-script-expected.txt +++ b/third_party/blink/web_tests/virtual/force-defer-script/defer-script/async-script-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE ERROR: line 3503: Uncaught Error: assert_equals: Normal script execution order comparison expected "Inline1;Sync1;EndOfBody;DOMContentLoaded;Async1;" but got "EndOfBody;Inline1;Sync1;DOMContentLoaded;Async1;" +CONSOLE ERROR: line 3346: Uncaught Error: assert_equals: Normal script execution order comparison expected "Inline1;Sync1;EndOfBody;DOMContentLoaded;Async1;" but got "EndOfBody;Inline1;Sync1;DOMContentLoaded;Async1;" This is a testharness.js-based test. FAIL Async Script Execution Order (wrt possibly deferred Synchronous Script) Uncaught Error: assert_equals: Normal script execution order comparison expected "Inline1;Sync1;EndOfBody;DOMContentLoaded;Async1;" but got "EndOfBody;Inline1;Sync1;DOMContentLoaded;Async1;" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/force-defer-script/defer-script/defer-script-expected.txt b/third_party/blink/web_tests/virtual/force-defer-script/defer-script/defer-script-expected.txt index ec885da..2f9f63a 100644 --- a/third_party/blink/web_tests/virtual/force-defer-script/defer-script/defer-script-expected.txt +++ b/third_party/blink/web_tests/virtual/force-defer-script/defer-script/defer-script-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE ERROR: line 3503: Uncaught Error: assert_equals: Normal defer script execution order comparison expected "Inline1;Sync1;Inline2;Sync2;EndOfBody;Defer1;Defer2;DOMContentLoaded;" but got "EndOfBody;Inline1;Sync1;Inline2;Sync2;Defer1;Defer2;DOMContentLoaded;" +CONSOLE ERROR: line 3346: Uncaught Error: assert_equals: Normal defer script execution order comparison expected "Inline1;Sync1;Inline2;Sync2;EndOfBody;Defer1;Defer2;DOMContentLoaded;" but got "EndOfBody;Inline1;Sync1;Inline2;Sync2;Defer1;Defer2;DOMContentLoaded;" This is a testharness.js-based test. FAIL Defer Script Execution Order Uncaught Error: assert_equals: Normal defer script execution order comparison expected "Inline1;Sync1;Inline2;Sync2;EndOfBody;Defer1;Defer2;DOMContentLoaded;" but got "EndOfBody;Inline1;Sync1;Inline2;Sync2;Defer1;Defer2;DOMContentLoaded;" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/origin/assorted.window-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/origin/assorted.window-expected.txt new file mode 100644 index 0000000..6b30c4e4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/fetch/origin/assorted.window-expected.txt
@@ -0,0 +1,46 @@ +This is a testharness.js-based test. +PASS Origin header and 308 redirect +PASS Origin header and GET navigation +PASS Origin header and POST navigation +PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer +FAIL Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +FAIL Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer +FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer +PASS Origin header and POST same-origin navigation with Referrer-Policy same-origin +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy same-origin +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and POST cross-origin navigation with Referrer-Policy same-origin +FAIL Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy same-origin assert_equals: expected "null" but got "http://web-platform.test:8001" +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy same-origin +PASS Origin header and POST same-origin navigation with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin navigation with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy origin-when-cross-origin +PASS Origin header and POST same-origin navigation with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin navigation with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy no-referrer-when-downgrade +PASS Origin header and POST same-origin navigation with Referrer-Policy unsafe-url +PASS Origin header and POST same-origin fetch no-cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST same-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET same-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin navigation with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin fetch no-cors mode with Referrer-Policy unsafe-url +PASS Origin header and POST cross-origin fetch cors mode with Referrer-Policy unsafe-url +PASS Origin header and GET cross-origin fetch cors mode with Referrer-Policy unsafe-url +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt index 2524912..9b2d07d 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
@@ -15,6 +15,7 @@ animationName animationPlayState animationTimingFunction +appearance backdropFilter backfaceVisibility background
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt index ce48d5ac..ef35f66 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/css-property-listing-expected.txt
@@ -3,7 +3,6 @@ [LONGHANDS] -webkit-app-region - -webkit-appearance -webkit-border-horizontal-spacing -webkit-border-image -webkit-border-vertical-spacing @@ -71,6 +70,7 @@ animation-name animation-play-state animation-timing-function + appearance backdrop-filter backface-visibility background-attachment @@ -677,6 +677,8 @@ animation-play-state -webkit-animation-timing-function animation-timing-function + -webkit-appearance + appearance -webkit-backface-visibility backface-visibility -webkit-background-clip
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/simulcast/basic.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/simulcast/basic.https-expected.txt new file mode 100644 index 0000000..5f33fd4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/simulcast/basic.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Basic simulcast setup with three spatial layers promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt index 6efcd28..2ffd5d1 100644 --- a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
@@ -15,6 +15,7 @@ animationName animationPlayState animationTimingFunction +appearance aspectRatio backdropFilter backfaceVisibility
diff --git a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt index 563ba73..7abedf1 100644 --- a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
@@ -3,7 +3,6 @@ [LONGHANDS] -webkit-app-region - -webkit-appearance -webkit-border-horizontal-spacing -webkit-border-image -webkit-border-vertical-spacing @@ -71,6 +70,7 @@ animation-name animation-play-state animation-timing-function + appearance aspect-ratio backdrop-filter backface-visibility @@ -753,6 +753,8 @@ animation-play-state -webkit-animation-timing-function animation-timing-function + -webkit-appearance + appearance -webkit-backface-visibility backface-visibility -webkit-background-clip
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-032.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-032.html index 940395b..b2704536 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-032.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-032.html
@@ -40,11 +40,13 @@ const target = document.getElementById("target"); let axTarget = axElementById("target"); t.step(() => { assert_false(axTarget.isIgnored); }); - - // Expect 7 children: 4 text nodes ("target" and whitespace between the divs) and 3 div children. + // Expect 7 children: 4 text nodes ("target" text and whitespace between the divs) and 3 div children. + // This is because #target is locked, and thus is saved as an AXNodeObject instead of an AXLayoutObject, + // so we have the separate <newline> text children because AXNodeObject does not do whitespace + // collapsing (though this might change in the future). // TODO(rakina): Make display:none, visiblity:hidden be ignored/not included in tree even when // display target, and make sure whitespace collapsing happen. - t.step(() => { assert_equals(axTarget.childrenCount, 7, "Child count after acquire"); }); + t.step(() => { assert_equals(axTarget.childrenCount, 7, "Children count when locked"); }); // These children are special because their "isVisible" should be false. const displayNoneIndex = 3; @@ -63,27 +65,14 @@ } } - axTarget = axElementById("target"); - t.step(() => { assert_equals(axTarget.childrenCount, 7, "Child count after update"); }); - - // Should stay the same as after acquiring. - for (let i = 0; i < axTarget.childrenCount; ++i) { - const axChild = axTarget.childAtIndex(i); - t.step(() => { assert_false(axChild.isIgnored, "After update, isIgnored is false on child #" + i); }); - if (i == displayNoneIndex || i == visibilityHiddenIndex) { - t.step(() => { assert_false(axChild.isVisible, "After update, isVisible is false on child #" + i); }); - } else { - t.step(() => { assert_true(axChild.isVisible, "After update, isVisible is true on child #" + i); }); - } - } - - // Remove subtree-visibility and force a layout recalc. + // Remove subtree-visibility and force a layout recalc, causing #target to get unlocked. target.classList.remove("auto"); requestAnimationFrame(() => requestAnimationFrame(() => { target.getBoundingClientRect(); axTarget = axElementById("target"); - // Expect 4 children: the text node "target" and 3 div children (#child, #displayNone, and #hidden). - t.step(() => { assert_equals(axTarget.childrenCount, 4, "Child count after commit"); }); + // Now that #target is not locked, it is saved as a normal AXLayout object and has 4 children: + // the text node "target" and 3 div children (#child, #displayNone, and #hidden). + t.step(() => { assert_equals(axTarget.childrenCount, 4, "Children count when not locked"); }); for (let i = 0; i < axTarget.childrenCount; ++i) { const axChild = axTarget.childAtIndex(i);
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-033.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-033.html index 1eac930..7886ded 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-033.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-033.html
@@ -32,14 +32,14 @@ let target = document.getElementById("target"); let axTarget = axElementById("target"); t.step(() => { assert_false(axTarget.isIgnored); }); - t.step(() => { assert_equals(axTarget.childrenCount, 0); }); + t.step(() => { assert_equals(axTarget.childrenCount, 0, "When locked, nodes in hidden subtree are ignored"); }); target.classList.remove("hidden"); requestAnimationFrame(() => requestAnimationFrame(() => { // The ax object for #target got replaced since the layout object changed, so use the new ax object. axTarget = axElementById("target"); - t.step(() => { assert_equals(axTarget.childrenCount, 2, "After commit, nodes in target subtree are not ignored"); }); + t.step(() => { assert_equals(axTarget.childrenCount, 2, "After getting unlocked, nodes in hidden subtree are not ignored"); }); t.done(); })); -}, "Nodes in target non-activatable tree are not exposed to accessibility tree"); +}, "Nodes in hidden non-activatable tree are not exposed to accessibility tree"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html index c407c6b..c282a9a 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html
@@ -4,12 +4,14 @@ <title>Subtree Visibility: accessibility focus</title> <link rel="author" title="Rakina Zata Amni" href="mailto:rakina@chromium.org"> <link rel="help" href="https://github.com/WICG/display-locking"> -<link rel="match" href="container-ref.html"> <meta name="assert" content="subtree-visibility auto subtrees are exposed by accessibility focus"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<div style="height:10000px;"> + spacer so that everything below will be offscreen (and won't get viewport-activated) +</div> <div id="hidden" style="subtree-visibility: auto"> foo <div id="child" tabindex="0"> @@ -23,25 +25,25 @@ } async_test(async(t) => { - t.step(() => { - let axChild = axElementById("child"); - assert_false(Boolean(axChild.backgroundColor), "Background color after activation"); - }); + const hiddenEl = document.getElementById("hidden"); + let axHidden = axElementById("hidden"); + // #hidden is locked, and thus is saved as an AXNodeObject instead of an AXLayoutObject, + // and has 3 child nodes: "foo" text, "<newline>" text, and #child node. + // Note that we have the separate <newline> text because it's an AXNodeObject and does + // not do whitespace collapsing (though this might change in the future). + t.step(() => { assert_equals(axHidden.childrenCount, 3, "Children count when locked"); }); - axElementById("child").takeFocus(); // Use accessibility to set the focus. - - // Wait for a few frames for the ax tree to be refreshed. + // Focus to #child, causing #hidden to get unlocked. + axElementById("child").takeFocus(); + // Wait for the next frame for the ax object to be recreated. requestAnimationFrame(() => { requestAnimationFrame(() => { -- requestAnimationFrame(() => { - - t.step(() => { - let axChild = axElementById("child"); - assert_equals(axChild.backgroundColor, 0xFFFFFFFF, "Background color after activation"); - }); - t.done(); - }); + axHidden = axElementById("hidden"); + // #hidden is now unlocked and saved as a normal AXLayoutObject with 2 child nodes: + // "foo" text and #child node. + t.step(() => { assert_equals(axHidden.childrenCount, 2, "Children count after activation"); }); + t.done(); }); }); -}, "Accessiblility focus causes activatable hidden tree to activate, and thus accessibility details such as background color become available"); - +}, "Accessiblility focus causes activatable hidden tree to activate"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-052.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-052.html index 27f6080e..dd2e315 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-052.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-052.html
@@ -4,18 +4,14 @@ <title>Subtree Visibility: accessibility press</title> <link rel="author" title="Rakina Zata Amni" href="mailto:rakina@chromium.org"> <link rel="help" href="https://github.com/WICG/display-locking"> -<link rel="match" href="container-ref.html"> <meta name="assert" content="subtree-visibility auto subtrees are exposed by accessibility press"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<style> -.auto { - subtree-visibility: auto; -} -</style> - +<div style="height:10000px;"> + spacer so that everything below will be offscreen (and won't get viewport-activated) +</div> <div id="hidden" style="subtree-visibility: auto"> foo <div id="child" tabindex="0"> @@ -28,18 +24,24 @@ return accessibilityController.accessibleElementById(id); } +// #hidden is locked, and thus is saved as an AXNodeObject instead of an AXLayoutObject, +// and has 3 child nodes: "foo" text, "<newline>" text, and #child node. +// Note that we have the separate <newline> text because it's an AXNodeObject and does +// not do whitespace collapsing (though this might change in the future). async_test(async(t) => { const hiddenEl = document.getElementById("hidden"); let axHidden = axElementById("hidden"); - t.step(() => { assert_equals(axHidden.childrenCount, 3, "Child count after acquire"); }); + t.step(() => { assert_equals(axHidden.childrenCount, 3, "Children count when locked"); }); + // This should unlock #hidden. axElementById("child").press(); - // Wait for the next frame for the ax object to be recreated. requestAnimationFrame(() => { requestAnimationFrame(() => { axHidden = axElementById("hidden"); - t.step(() => { assert_equals(axHidden.childrenCount, 2, "Child count after activation"); }); + // #hidden is now unlocked and saved as a normal AXLayoutObject with 2 child nodes: + // "foo" text and #child node. + t.step(() => { assert_equals(axHidden.childrenCount, 2, "Children count after activation"); }); t.done(); }); });
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-053.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-053.html index 85dcb71..9dca6b56 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-053.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-053.html
@@ -9,17 +9,10 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<style> -.spacer { - height: 3000px; -} -.auto { - subtree-visibility: auto; -} -</style> - -<div class=spacer></div> -<div id="hidden" class=auto> +<div style="height:10000px;"> + spacer so that everything below will be offscreen (and won't get viewport-activated) +</div> +<div id="hidden" style="subtree-visibility: auto"> foo <div id="child" tabindex="0"> bar @@ -35,8 +28,13 @@ async_test(async(t) => { const hiddenEl = document.getElementById("hidden"); let axHidden = axElementById("hidden"); - t.step(() => { assert_equals(axHidden.childrenCount, 3, "Child count after acquire"); }); + // #hidden is locked, and thus is saved as an AXNodeObject instead of an AXLayoutObject, + // and has 3 child nodes: "foo" text, "<newline>" text, and #child node. + // Note that we have the separate <newline> text because it's an AXNodeObject and does + // not do whitespace collapsing (though this might change in the future).. + t.step(() => { assert_equals(axHidden.childrenCount, 3, "Children count when locked"); }); + // This should unlock #hidden. axElementById("child").scrollToMakeVisible(); // If this is frame 1, then during frame 2, we will determine that we're
diff --git a/third_party/bouncycastle/README.chromium b/third_party/bouncycastle/README.chromium index 6bedd00..b0f55a4 100644 --- a/third_party/bouncycastle/README.chromium +++ b/third_party/bouncycastle/README.chromium
@@ -1,6 +1,7 @@ Name: Bouncy Castle URL: https://www.bouncycastle.org/java.html Version: 1.46 +CPEPrefix: cpe:/a:bouncycastle:fips_java_api:1.46 License: MIT License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/checkstyle/README.chromium b/third_party/checkstyle/README.chromium index d2d234a..0938fa1 100644 --- a/third_party/checkstyle/README.chromium +++ b/third_party/checkstyle/README.chromium
@@ -3,6 +3,7 @@ Short Name: checkstyle URL: https://github.com/checkstyle/checkstyle Version: 8.15 +CPEPrefix: cpe:/a:checkstyle:checkstyle:8.15 License: LGPL 2.1 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/d3/README.chromium b/third_party/d3/README.chromium index d3fcf14..a5f9893 100644 --- a/third_party/d3/README.chromium +++ b/third_party/d3/README.chromium
@@ -2,6 +2,7 @@ Short Name: d3 URL: https://github.com/d3/d3 Version: 5.7.0 +CPEPrefix: cpe:/a:d3.js_project:d3.js:5.7.0::~~~node.js~~ Date: Fri Aug 24 5:46 PM 2018 EDT Revision: e35d1f74f9337a2eee4aa704f38025621c8ae9d0 License: BSD 3-Clause
diff --git a/third_party/devscripts/README.chromium b/third_party/devscripts/README.chromium index cae5d0a..5019458 100644 --- a/third_party/devscripts/README.chromium +++ b/third_party/devscripts/README.chromium
@@ -1,6 +1,7 @@ Name: devscripts URL: http://anonscm.debian.org/gitweb/?p=devscripts/devscripts.git Version: 2.12.4 +CPEPrefix: cpe:/a:debian:devscripts:2.12.4 Security Critical: no License: GPL 2.0 License File: NOT_SHIPPED
diff --git a/third_party/fontconfig/README.chromium b/third_party/fontconfig/README.chromium index 0527e45..2355a647 100644 --- a/third_party/fontconfig/README.chromium +++ b/third_party/fontconfig/README.chromium
@@ -1,6 +1,7 @@ Name: fontconfig URL: http://www.freedesktop.org/wiki/Software/fontconfig/ Version: 452be8125f0e2a18a7dfef469e05d19374d36307 +CPEPrefix: cpe:/a:fontconfig_project:fontconfig:2.13.91 License: MIT License File: src/COPYING Security Critical: yes
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 129e70e..26cf50ca 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -2,6 +2,7 @@ URL: http://www.freetype.org/ Version: VER-2-10-1-113-g13c0df80d Revision: 13c0df80dca59ce2ef3ec125b08c5b6ea485535c +CPEPrefix: cpe:/a:freetype:freetype:2.10.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/guava/README.chromium b/third_party/guava/README.chromium index 12ec68e3..f31dc74 100644 --- a/third_party/guava/README.chromium +++ b/third_party/guava/README.chromium
@@ -2,6 +2,7 @@ Short Name: guava URL: https://github.com/google/guava Version: 23.0 +CPEPrefix: cpe:/a:google:guava:23.0:rc1 License: Apache 2.0 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/hunspell/README.chromium b/third_party/hunspell/README.chromium index cb0eb94..1bb154a50 100644 --- a/third_party/hunspell/README.chromium +++ b/third_party/hunspell/README.chromium
@@ -1,6 +1,7 @@ Name: hunspell URL: http://hunspell.sourceforge.net/ Version: 1.6.0 +CPEPrefix: cpe:/a:hunspell_project:hunspell:1.6.0 License: MPL 1.1/GPL 2.0/LGPL 2.1 License File: COPYING.MPL Security Critical: yes
diff --git a/third_party/jdk/README.chromium b/third_party/jdk/README.chromium index cdfca5b4..8481c3a 100644 --- a/third_party/jdk/README.chromium +++ b/third_party/jdk/README.chromium
@@ -2,6 +2,7 @@ Short Name: JDK URL: https://www.java.com/ Version: 11.0.4 +CPEPrefix: cpe:/a:oracle:jdk:11.0.4 License: GPL v2 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/jinja2/README.chromium b/third_party/jinja2/README.chromium index 5246c2f..9b8311a 100644 --- a/third_party/jinja2/README.chromium +++ b/third_party/jinja2/README.chromium
@@ -2,6 +2,7 @@ Short Name: jinja2 URL: http://jinja.pocoo.org/ Version: 2.10 +CPEPrefix: cpe:/a:pocoo:jinja2:2.10 License: BSD 3-Clause License File: LICENSE Security Critical: no
diff --git a/third_party/jsoncpp/README.chromium b/third_party/jsoncpp/README.chromium index 48bc543..da90c30 100644 --- a/third_party/jsoncpp/README.chromium +++ b/third_party/jsoncpp/README.chromium
@@ -1,6 +1,7 @@ Name: jsoncpp URL: https://github.com/open-source-parsers/jsoncpp -Version: f572e8e42e22cfcf5ab0aea26574f408943edfa4 +Version: 645250b6690785be60ab6780ce4b58698d884d11 +CPEPrefix: cpe:/a:jsoncpp_project:jsoncpp:1.9.1 License: MIT License File: LICENSE Security Critical: yes
diff --git a/third_party/junit/README.chromium b/third_party/junit/README.chromium index ddd5a553..26fead7 100644 --- a/third_party/junit/README.chromium +++ b/third_party/junit/README.chromium
@@ -1,6 +1,7 @@ Name: JUnit URL: http://junit.org Version: 4.12 +CPEPrefix: cpe:/a:jenkins:junit:4.12::~~~jenkins~~ License: Common Public License 1.0 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/liblouis/README.chromium b/third_party/liblouis/README.chromium index cbbbd61..0fcb3cd0 100644 --- a/third_party/liblouis/README.chromium +++ b/third_party/liblouis/README.chromium
@@ -2,6 +2,7 @@ Short Name: liblouis URL: https://github.com/liblouis/liblouis Version: 3.12.0 +CPEPrefix: cpe:/a:liblouis:liblouis:3.12.0 License: LGPL3 and GPL3 License Android Compatible: No License File: LICENSE
diff --git a/third_party/libusb/README.chromium b/third_party/libusb/README.chromium index d2301774..071a981 100644 --- a/third_party/libusb/README.chromium +++ b/third_party/libusb/README.chromium
@@ -1,6 +1,7 @@ Name: libusbx URL: http://libusb.org Version: 1.0.17 +CPEPrefix: cpe:/a:libusb:libusb:1.0.17:rc1 License: LGPL 2.1 License File: src/COPYING Security Critical: yes
diff --git a/third_party/libwebm/README.chromium b/third_party/libwebm/README.chromium index 7d3b804..6a3fcd52 100644 --- a/third_party/libwebm/README.chromium +++ b/third_party/libwebm/README.chromium
@@ -2,6 +2,7 @@ Short Name: libwebm URL: http://www.webmproject.org/code/ Version: unknown +CPEPrefix: cpe:/a:webmproject:libwebm:1.0.0.27 License: BSD License File: source/LICENSE.TXT Security Critical: yes
diff --git a/third_party/libwebp/README.chromium b/third_party/libwebp/README.chromium index 0a911d0..768d6de 100644 --- a/third_party/libwebp/README.chromium +++ b/third_party/libwebp/README.chromium
@@ -2,6 +2,7 @@ Short Name: libwebp URL: http://developers.google.com/speed/webp Version: v1.1.0 +CPEPrefix: cpe:/a:webmproject:libwebp:1.1.0 License: BSD License File: LICENSE Security Critical: Yes
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium index 2aa8772..bbe3179 100644 --- a/third_party/libxml/README.chromium +++ b/third_party/libxml/README.chromium
@@ -1,6 +1,7 @@ Name: libxml URL: http://xmlsoft.org Version: a7fe7ee45938c53a8dd028dd40baa461191a2fd2 +CPEPrefix: cpe:/a:xmlsoft:libxml2:2.9.9 License: MIT License File: src/Copyright Security Critical: yes
diff --git a/third_party/logilab/logilab/common/README.chromium b/third_party/logilab/logilab/common/README.chromium index fdc9991..8283ad6 100644 --- a/third_party/logilab/logilab/common/README.chromium +++ b/third_party/logilab/logilab/common/README.chromium
@@ -1,6 +1,7 @@ URL: http://www.logilab.org/project/logilab-common Name: logilab-common Version: 0.63.2 +CPEPrefix: cpe:/a:logilab:logilab-common:0.63.2 License: GPL v2 License File: LICENSE.txt Security Critical: No
diff --git a/third_party/markdown/README.chromium b/third_party/markdown/README.chromium index a376550..4e292a0 100644 --- a/third_party/markdown/README.chromium +++ b/third_party/markdown/README.chromium
@@ -2,6 +2,7 @@ Short Name: markdown URL: https://pypi.python.org/pypi/Markdown Version: 2.3.1 +CPEPrefix: cpe:/a:cebe:markdown:2.3.1 Date: March 22, 2013 Revision: commit 0ea0bac85a749a13381b721cde44214d9193406c License: BSD 3-Clause
diff --git a/third_party/mesa_headers/README.chromium b/third_party/mesa_headers/README.chromium index 03f9ee52..a5ed85a 100644 --- a/third_party/mesa_headers/README.chromium +++ b/third_party/mesa_headers/README.chromium
@@ -1,5 +1,6 @@ Name: mesa_headers Version: 9.0.3 +CPEPrefix: cpe:/a:mesa3d:mesa:9.0.3 URL: http://www.mesa3d.org/ License: MIT and SGI Free Software B License Version 2.0 Security Critical: Yes
diff --git a/third_party/minizip/README.chromium b/third_party/minizip/README.chromium index cc7f42b..3a30e02 100644 --- a/third_party/minizip/README.chromium +++ b/third_party/minizip/README.chromium
@@ -2,6 +2,7 @@ Short name: minizip URL: https://github.com/nmoinvaz/minizip Version: 2.8.1 +CPEPrefix: cpe:/a:minizip_project:minizip:2.8.1 Revision: 1ff40343b55e738d941abb51c70eddb803db16e2 Security critical: yes License: Custom license
diff --git a/third_party/mozilla/README.chromium b/third_party/mozilla/README.chromium index 9ea000df..085e486 100644 --- a/third_party/mozilla/README.chromium +++ b/third_party/mozilla/README.chromium
@@ -2,6 +2,7 @@ Short Name: camino URL: http://caminobrowser.org/ Version: unknown +CPEPrefix: unknown License: MPL 1.1/GPL 2.0/LGPL 2.1 Security Critical: yes
diff --git a/third_party/openh264/README.chromium b/third_party/openh264/README.chromium index 3d17eda..4f5b9fd 100644 --- a/third_party/openh264/README.chromium +++ b/third_party/openh264/README.chromium
@@ -2,6 +2,7 @@ Short Name: openh264 URL: http://www.openh264.org/ Version: unknown +CPEPrefix: cpe:/a:cisco:openh264:1.9.0 (Cut at 6f26bce0b1c4e8ce0e13332f7c0083788def5fdf, which is between 1.9.0 and 1.10.0) License: 2-Clause BSD
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium index a42e244..dc47470 100644 --- a/third_party/protobuf/README.chromium +++ b/third_party/protobuf/README.chromium
@@ -4,6 +4,7 @@ License: BSD License File: LICENSE Version: 3.9.0 +CPEPrefix: cpe:/a:google:protobuf:3.9.0 Revision: cf242503ec157a7dda8a6eda48712dd26c81d2e6 Security Critical: yes
diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index 58f46ae..5d6ff82 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium
@@ -10,25 +10,14 @@ R8 is a proguard-like optimizer that also has the ability to dex. Local Modifications: -Turning off vertical and horizontal class merging, as described in -https://issuetracker.google.com/122902374#comment11. We should no longer make -this modification once the linked bug is fixed. - -Turning off outlining because it caused issues when synchronized proguarding -Trichrome due to illegal dex references (crbug.com/956839). Will only be used -for android_apk() targets that set `disable_r8_outlining = true`): - -Added --feature-jar flag for doing dex splitting. - -local_modifications.diff created via: -git diff >local_modifications.diff +* Refer to commit descriptions within "patches" directory. Update Instructions: # Download R8: git clone https://r8.googlesource.com/r8 cd r8 -# Apply the patch: -git apply $CHROMIUM_SRC/third_party/r8/local_modifications.diff +# Apply patches: +git am $CHROMIUM_SRC/third_party/r8/patches *.patch # Build: tools/gradle.py r8 # Shrink (improves r8/d8 launch time): @@ -44,3 +33,7 @@ # Manually update: * README.chromium (version number via "java -jar lib/r8.jar --version") * //DEPS (instance ID output by cipd create) + +# To create a new patch: +* Make commits to the r8 repro +* Run: git format-patch $R8_REVISION_BEFORE_PATCHES
diff --git a/third_party/r8/local_modifications.diff b/third_party/r8/local_modifications.diff deleted file mode 100644 index 8b695e0..0000000 --- a/third_party/r8/local_modifications.diff +++ /dev/null
@@ -1,120 +0,0 @@ -diff --git a/src/main/java/com/android/tools/r8/D8CommandParser.java b/src/main/java/com/android/tools/r8/D8CommandParser.java -index f66fff8f3..c63f4f566 100644 ---- a/src/main/java/com/android/tools/r8/D8CommandParser.java -+++ b/src/main/java/com/android/tools/r8/D8CommandParser.java -@@ -205,7 +205,7 @@ public class D8CommandParser extends BaseCompilerCommandParser<D8Command, D8Comm - } - compilationMode = CompilationMode.RELEASE; - } else if (arg.equals("--file-per-class")) { -- outputMode = OutputMode.DexFilePerClass; -+ outputMode = OutputMode.DexFilePerClassFile; - } else if (arg.equals("--output")) { - if (outputPath != null) { - builder.error( -diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java -index 4051f9cef..6d034d5b8 100644 ---- a/src/main/java/com/android/tools/r8/R8Command.java -+++ b/src/main/java/com/android/tools/r8/R8Command.java -@@ -42,6 +42,8 @@ import java.util.function.BiPredicate; - import java.util.function.Consumer; - import java.util.function.Function; - -+import com.android.tools.r8.DexIndexedConsumer.DirectoryConsumer; -+ - /** - * Immutable command structure for an invocation of the {@link R8} compiler. - * -@@ -234,6 +236,15 @@ public final class R8Command extends BaseCompilerCommand { - return self(); - } - -+ public Builder addFeatureJar(Path inputJarPath, Path outputPath) { -+ addFeatureSplit(splitBuilder -> -+ splitBuilder -+ .addProgramResourceProvider(ArchiveProgramResourceProvider.fromArchive(inputJarPath)) -+ .setProgramConsumer(new DirectoryConsumer(outputPath)) -+ .build()); -+ return self(); -+ } -+ - /** - * Set a consumer for receiving the proguard-map content. - * -diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java -index 22ebb5e42..b53e4c59e 100644 ---- a/src/main/java/com/android/tools/r8/R8CommandParser.java -+++ b/src/main/java/com/android/tools/r8/R8CommandParser.java -@@ -24,6 +24,7 @@ public class R8CommandParser extends BaseCompilerCommandParser<R8Command, R8Comm - "--min-api", - "--main-dex-rules", - "--main-dex-list", -+ "--feature-jar", - "--main-dex-list-output", - "--pg-conf", - "--pg-map-output", -@@ -205,6 +206,11 @@ public class R8CommandParser extends BaseCompilerCommandParser<R8Command, R8Comm - builder.setDisableDesugaring(true); - } else if (arg.equals("--main-dex-rules")) { - builder.addMainDexRulesFiles(Paths.get(nextArg)); -+ } else if (arg.equals("--feature-jar")) { -+ String[] argParts = nextArg.split(":"); -+ String featureJarInputPath = argParts[0]; -+ String featureJarOutputPath = argParts[1]; -+ builder.addFeatureJar(Paths.get(featureJarInputPath), Paths.get(featureJarOutputPath)); - } else if (arg.equals("--main-dex-list")) { - builder.addMainDexListFiles(Paths.get(nextArg)); - } else if (arg.equals("--main-dex-list-output")) { -diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java -index 0831e6d93..49c1a202b 100644 ---- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java -+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java -@@ -206,7 +206,7 @@ public final class LambdaClass { - } - - public final boolean isStateless() { -- return descriptor.isStateless(); -+ return false; // descriptor.isStateless(); - } - - void addSynthesizedFrom(DexProgramClass clazz) { -diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -index 232b54a54..fd45dfe36 100644 ---- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java -+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -@@ -198,8 +198,8 @@ public class InternalOptions { - public boolean enableFieldAssignmentTracker = true; - public boolean enableFieldBitAccessAnalysis = - System.getProperty("com.android.tools.r8.fieldBitAccessAnalysis") != null; -- public boolean enableHorizontalClassMerging = true; -- public boolean enableVerticalClassMerging = true; -+ public boolean enableHorizontalClassMerging = System.getProperty("com.android.tools.r8.enableHorizontalClassMerging") != null; -+ public boolean enableVerticalClassMerging = System.getProperty("com.android.tools.r8.enableVerticalClassMerging") != null; - public boolean enableArgumentRemoval = true; - public boolean enableUnusedArgumentRemoval = true; - public boolean enableUnusedInterfaceRemoval = true; -@@ -956,7 +956,7 @@ public class InternalOptions { - public static final String CLASS_NAME = "com.android.tools.r8.GeneratedOutlineSupport"; - public static final String METHOD_PREFIX = "outline"; - -- public boolean enabled = true; -+ public boolean enabled = System.getProperty("com.android.tools.r8.disableOutlining") == null; - public int minSize = 3; - public int maxSize = 99; - public int threshold = 20; -diff --git a/src/main/keep.txt b/src/main/keep.txt -index b0c58c916..5e4405175 100644 ---- a/src/main/keep.txt -+++ b/src/main/keep.txt -@@ -27,4 +27,10 @@ - -keep public class com.android.tools.r8.compatproguard.CompatProguard { public static void main(java.lang.String[]); } - - # Compatibility command line program used by in google3. ---keep public class com.android.tools.r8.compatdx.CompatDx { public static void main(java.lang.String[]); } -\ No newline at end of file -+-keep public class com.android.tools.r8.compatdx.CompatDx { public static void main(java.lang.String[]); } -+ -+-keep public class com.android.tools.r8.SwissArmyKnife { *; } -+ -+# Chrome: We want to maintain stack traces from the R8 tool, so disable -+# optimizations. -+-dontoptimize
diff --git a/third_party/r8/patches/0001-Chrome-Change-meaning-of-file-per-class.patch b/third_party/r8/patches/0001-Chrome-Change-meaning-of-file-per-class.patch new file mode 100644 index 0000000..be387522 --- /dev/null +++ b/third_party/r8/patches/0001-Chrome-Change-meaning-of-file-per-class.patch
@@ -0,0 +1,29 @@ +From 0cc1077ef5dcdccafc5f526e682dff88d46c67ff Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 1 Apr 2020 09:59:30 -0400 +Subject: [PATCH 1/5] Chrome: Change meaning of --file-per-class + +Make it mean OutputMode.DexFilePerClassFile instead of +OutputMode.DexFilePerClass. + +Fixes Chrome's incremental dexing logic. +--- + src/main/java/com/android/tools/r8/D8CommandParser.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/main/java/com/android/tools/r8/D8CommandParser.java b/src/main/java/com/android/tools/r8/D8CommandParser.java +index f66fff8f3..c63f4f566 100644 +--- a/src/main/java/com/android/tools/r8/D8CommandParser.java ++++ b/src/main/java/com/android/tools/r8/D8CommandParser.java +@@ -205,7 +205,7 @@ public class D8CommandParser extends BaseCompilerCommandParser<D8Command, D8Comm + } + compilationMode = CompilationMode.RELEASE; + } else if (arg.equals("--file-per-class")) { +- outputMode = OutputMode.DexFilePerClass; ++ outputMode = OutputMode.DexFilePerClassFile; + } else if (arg.equals("--output")) { + if (outputPath != null) { + builder.error( +-- +2.26.0.rc2.310.g2932bb562d-goog +
diff --git a/third_party/r8/patches/0002-Adds-feature-jar-to-R8-command.patch b/third_party/r8/patches/0002-Adds-feature-jar-to-R8-command.patch new file mode 100644 index 0000000..1120f38 --- /dev/null +++ b/third_party/r8/patches/0002-Adds-feature-jar-to-R8-command.patch
@@ -0,0 +1,67 @@ +From 497bfde1cf89ca66777dcb3314c4eef331d3e7ab Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 1 Apr 2020 10:03:06 -0400 +Subject: [PATCH 2/5] Adds --feature-jar to R8 command + +Chrome needs this to expose feature splits via command-line +--- + src/main/java/com/android/tools/r8/R8Command.java | 11 +++++++++++ + .../java/com/android/tools/r8/R8CommandParser.java | 6 ++++++ + 2 files changed, 17 insertions(+) + +diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java +index 4051f9cef..6d034d5b8 100644 +--- a/src/main/java/com/android/tools/r8/R8Command.java ++++ b/src/main/java/com/android/tools/r8/R8Command.java +@@ -42,6 +42,8 @@ import java.util.function.BiPredicate; + import java.util.function.Consumer; + import java.util.function.Function; + ++import com.android.tools.r8.DexIndexedConsumer.DirectoryConsumer; ++ + /** + * Immutable command structure for an invocation of the {@link R8} compiler. + * +@@ -234,6 +236,15 @@ public final class R8Command extends BaseCompilerCommand { + return self(); + } + ++ public Builder addFeatureJar(Path inputJarPath, Path outputPath) { ++ addFeatureSplit(splitBuilder -> ++ splitBuilder ++ .addProgramResourceProvider(ArchiveProgramResourceProvider.fromArchive(inputJarPath)) ++ .setProgramConsumer(new DirectoryConsumer(outputPath)) ++ .build()); ++ return self(); ++ } ++ + /** + * Set a consumer for receiving the proguard-map content. + * +diff --git a/src/main/java/com/android/tools/r8/R8CommandParser.java b/src/main/java/com/android/tools/r8/R8CommandParser.java +index 22ebb5e42..b53e4c59e 100644 +--- a/src/main/java/com/android/tools/r8/R8CommandParser.java ++++ b/src/main/java/com/android/tools/r8/R8CommandParser.java +@@ -24,6 +24,7 @@ public class R8CommandParser extends BaseCompilerCommandParser<R8Command, R8Comm + "--min-api", + "--main-dex-rules", + "--main-dex-list", ++ "--feature-jar", + "--main-dex-list-output", + "--pg-conf", + "--pg-map-output", +@@ -205,6 +206,11 @@ public class R8CommandParser extends BaseCompilerCommandParser<R8Command, R8Comm + builder.setDisableDesugaring(true); + } else if (arg.equals("--main-dex-rules")) { + builder.addMainDexRulesFiles(Paths.get(nextArg)); ++ } else if (arg.equals("--feature-jar")) { ++ String[] argParts = nextArg.split(":"); ++ String featureJarInputPath = argParts[0]; ++ String featureJarOutputPath = argParts[1]; ++ builder.addFeatureJar(Paths.get(featureJarInputPath), Paths.get(featureJarOutputPath)); + } else if (arg.equals("--main-dex-list")) { + builder.addMainDexListFiles(Paths.get(nextArg)); + } else if (arg.equals("--main-dex-list-output")) { +-- +2.26.0.rc2.310.g2932bb562d-goog +
diff --git a/third_party/r8/patches/0003-Desugaring-Make-all-lambdas-stateless-fix-naming-sch.patch b/third_party/r8/patches/0003-Desugaring-Make-all-lambdas-stateless-fix-naming-sch.patch new file mode 100644 index 0000000..e57b97b --- /dev/null +++ b/third_party/r8/patches/0003-Desugaring-Make-all-lambdas-stateless-fix-naming-sch.patch
@@ -0,0 +1,39 @@ +From 6c3009d363b1e50adc83279dba27b4e0a350ead7 Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 1 Apr 2020 10:03:46 -0400 +Subject: [PATCH 3/5] Desugaring: Make all lambdas stateless & fix naming + scheme of method references + +Statefull lambdas regress dex size. + +Bug: b/129997269 +--- + .../java/com/android/tools/r8/ir/desugar/LambdaClass.java | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java +index 0831e6d93..0abb97180 100644 +--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java ++++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java +@@ -128,7 +128,8 @@ public final class LambdaClass { + // If the lambda class should match 1:1 the class it is accessed from, we + // just add the name of this type to make lambda class name unique. + // It also helps link the class lambda originated from in some cases. +- if (match.delegatesToLambdaImplMethod() || match.needsAccessor(accessedFrom)) { ++ if (true || match.delegatesToLambdaImplMethod() || match.needsAccessor(accessedFrom)) { ++ // Chrome: This class name is required for supersize to map the symbol to source .java file. + lambdaClassDescriptor.append(accessedFrom.getName()).append('$'); + } + +@@ -206,7 +207,7 @@ public final class LambdaClass { + } + + public final boolean isStateless() { +- return descriptor.isStateless(); ++ return false; // descriptor.isStateless(); + } + + void addSynthesizedFrom(DexProgramClass clazz) { +-- +2.26.0.rc2.310.g2932bb562d-goog +
diff --git a/third_party/r8/patches/0004-Make-class-merging-and-outlining-settable-via-comman.patch b/third_party/r8/patches/0004-Make-class-merging-and-outlining-settable-via-comman.patch new file mode 100644 index 0000000..d5037d68 --- /dev/null +++ b/third_party/r8/patches/0004-Make-class-merging-and-outlining-settable-via-comman.patch
@@ -0,0 +1,37 @@ +From c090e841899461437cc91adbdfc7c74ef8091a53 Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 1 Apr 2020 10:06:15 -0400 +Subject: [PATCH 4/5] Make class merging and outlining settable via + command-line + +--- + .../java/com/android/tools/r8/utils/InternalOptions.java | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java +index 232b54a54..fd45dfe36 100644 +--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java ++++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java +@@ -198,8 +198,8 @@ public class InternalOptions { + public boolean enableFieldAssignmentTracker = true; + public boolean enableFieldBitAccessAnalysis = + System.getProperty("com.android.tools.r8.fieldBitAccessAnalysis") != null; +- public boolean enableHorizontalClassMerging = true; +- public boolean enableVerticalClassMerging = true; ++ public boolean enableHorizontalClassMerging = System.getProperty("com.android.tools.r8.enableHorizontalClassMerging") != null; ++ public boolean enableVerticalClassMerging = System.getProperty("com.android.tools.r8.enableVerticalClassMerging") != null; + public boolean enableArgumentRemoval = true; + public boolean enableUnusedArgumentRemoval = true; + public boolean enableUnusedInterfaceRemoval = true; +@@ -956,7 +956,7 @@ public class InternalOptions { + public static final String CLASS_NAME = "com.android.tools.r8.GeneratedOutlineSupport"; + public static final String METHOD_PREFIX = "outline"; + +- public boolean enabled = true; ++ public boolean enabled = System.getProperty("com.android.tools.r8.disableOutlining") == null; + public int minSize = 3; + public int maxSize = 99; + public int threshold = 20; +-- +2.26.0.rc2.310.g2932bb562d-goog +
diff --git a/third_party/r8/patches/0005-Fix-up-proguard-keeps-for-Chrome.patch b/third_party/r8/patches/0005-Fix-up-proguard-keeps-for-Chrome.patch new file mode 100644 index 0000000..f42ab8ae --- /dev/null +++ b/third_party/r8/patches/0005-Fix-up-proguard-keeps-for-Chrome.patch
@@ -0,0 +1,29 @@ +From fe0cf2feb23d4cdcf4dc287bddba9ea07538aa35 Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 1 Apr 2020 10:06:57 -0400 +Subject: [PATCH 5/5] Fix up proguard keeps for Chrome + +--- + src/main/keep.txt | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/main/keep.txt b/src/main/keep.txt +index b0c58c916..5e4405175 100644 +--- a/src/main/keep.txt ++++ b/src/main/keep.txt +@@ -27,4 +27,10 @@ + -keep public class com.android.tools.r8.compatproguard.CompatProguard { public static void main(java.lang.String[]); } + + # Compatibility command line program used by in google3. +--keep public class com.android.tools.r8.compatdx.CompatDx { public static void main(java.lang.String[]); } +\ No newline at end of file ++-keep public class com.android.tools.r8.compatdx.CompatDx { public static void main(java.lang.String[]); } ++ ++-keep public class com.android.tools.r8.SwissArmyKnife { *; } ++ ++# Chrome: We want to maintain stack traces from the R8 tool, so disable ++# optimizations. ++-dontoptimize +-- +2.26.0.rc2.310.g2932bb562d-goog +
diff --git a/third_party/requests/README.chromium b/third_party/requests/README.chromium index ac14377..f9e12871 100644 --- a/third_party/requests/README.chromium +++ b/third_party/requests/README.chromium
@@ -1,6 +1,7 @@ Name: Requests URL: http://docs.python-requests.org/en/latest/ Version: 2.5.0 +CPEPrefix: cpe:/a:python-requests:requests:2.5.0 License: Apache Version 2.0 License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/simplejson/README.chromium b/third_party/simplejson/README.chromium index 1301c6a..6a1313e2 100644 --- a/third_party/simplejson/README.chromium +++ b/third_party/simplejson/README.chromium
@@ -1,6 +1,7 @@ Name: simplejson URL: https://github.com/simplejson/simplejson Version: 2.6.2 +CPEPrefix: cpe:/a:simplejson_project:simplejson:2.6.2::~~~python~~ License: MIT License File: LICENSE.txt Security Critical: no
diff --git a/third_party/snappy/README.chromium b/third_party/snappy/README.chromium index b7d03c4..896f2aaa 100644 --- a/third_party/snappy/README.chromium +++ b/third_party/snappy/README.chromium
@@ -2,6 +2,7 @@ Short Name: snappy URL: http://google.github.io/snappy/ Version: 1.1.7.git.3f194acb57e0487531c96b97af61dcbd025a78a3 +CPEPrefix: cpe:/a:google:snappy:1.1.7 License: New BSD License File: src/COPYING Security Critical: yes
diff --git a/third_party/sqlite/README.chromium b/third_party/sqlite/README.chromium index 455fd0fc..4eabc10 100644 --- a/third_party/sqlite/README.chromium +++ b/third_party/sqlite/README.chromium
@@ -1,6 +1,7 @@ Name: sqlite URL: https://sqlite.org/ Version: 3.31.1 +CPEPrefix: cpe:/a:sqlite:sqlite:3.31.1 Included In Release: Yes Security Critical: Yes License: Public domain
diff --git a/third_party/tlslite/README.chromium b/third_party/tlslite/README.chromium index 2725734..b189e12 100644 --- a/third_party/tlslite/README.chromium +++ b/third_party/tlslite/README.chromium
@@ -1,6 +1,7 @@ Name: tlslite URL: http://trevp.net/tlslite/ Version: 0.4.8 +CPEPrefix: cpe:/a:tlslite_project:tlslite:0.4.8::~~~python~~ Security Critical: No License: Public domain and BSD
diff --git a/third_party/wayland/README.chromium b/third_party/wayland/README.chromium index cebc3a5..f577a0cc 100644 --- a/third_party/wayland/README.chromium +++ b/third_party/wayland/README.chromium
@@ -1,6 +1,7 @@ Name: wayland URL: http://wayland.freedesktop.org/ Version: 1.17.0 +CPEPrefix: cpe:/a:wayland:wayland:1.17.0 License: MIT License File: src/COPYING Security Critical: yes
diff --git a/third_party/xstream/README.chromium b/third_party/xstream/README.chromium index 6568f65f..1e0397590 100644 --- a/third_party/xstream/README.chromium +++ b/third_party/xstream/README.chromium
@@ -1,6 +1,7 @@ Name: Xstream URL: https://x-stream.github.io/ Version: 1.4.8 +CPEPrefix: cpe:/a:xstream_project:xstream:1.4.8 License: BSD 3-Clause License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/zlib/README.chromium b/third_party/zlib/README.chromium index 3d90f79..c3c1ef6 100644 --- a/third_party/zlib/README.chromium +++ b/third_party/zlib/README.chromium
@@ -2,6 +2,7 @@ Short Name: zlib URL: http://zlib.net/ Version: 1.2.11 +CPEPrefix: cpe:/a:zlib:zlib:1.2.11 Security Critical: yes License: Custom license License File: LICENSE
diff --git a/tools/binary_size/libsupersize/apkanalyzer.py b/tools/binary_size/libsupersize/apkanalyzer.py index 460b9b8..9eba8fb 100644 --- a/tools/binary_size/libsupersize/apkanalyzer.py +++ b/tools/binary_size/libsupersize/apkanalyzer.py
@@ -7,6 +7,7 @@ Assumes that apk_path.mapping and apk_path.jar.info is available. """ +import collections import logging import os import subprocess @@ -135,6 +136,13 @@ return nodes +def _TruncateFrom(value, delimiter, rfind=False): + idx = value.rfind(delimiter) if rfind else value.find(delimiter) + if idx != -1: + return value[:idx] + return value + + def CreateDexSymbols(apk_path, mapping_path, size_info_prefix): source_map = _ParseJarInfoFile(size_info_prefix + '.jar.info') @@ -154,10 +162,33 @@ # We have more than 100KB of ids for methods, strings id_metadata_overhead_size = dex_expected_size - total_node_size symbols = [] + lambda_by_class_counter = collections.defaultdict(int) + lambda_name_to_nested_number = {} for _, name, node_size in nodes: - package = name.split(' ', 1)[0] - class_path = package.split('$')[0] - source_path = source_map.get(class_path, '') + package = _TruncateFrom(name, ' ') + # Make d8 desugared lambdas look the same as Desugar ones. + # D8 lambda: -$$Lambda$Promise$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex + # Desugar lambda: Promise$Nested1$$Lambda$0 + # 1) Need to prefix with proper class name so that they will show as nested. + # 2) Need to suffix with number so that they diff better. + # Original name will be kept as "object_path". + is_d8_lambda = '-$$Lambda$' in package + class_path = package + if is_d8_lambda: + class_path = package.replace('-$$Lambda$', '') + base_name = _TruncateFrom(class_path, '$', rfind=True) + # Map all methods of the lambda class to the same nested number. + lambda_number = lambda_name_to_nested_number.get(class_path) + if lambda_number is None: + # First time we've seen this lambda, increment nested class count. + lambda_number = lambda_by_class_counter[base_name] + lambda_name_to_nested_number[class_path] = lambda_number + lambda_by_class_counter[base_name] = lambda_number + 1 + + name = '{}$$Lambda${}{}'.format(base_name, lambda_number, + name[len(package):]) + # Map all nested classes to outer class. + source_path = source_map.get(_TruncateFrom(class_path, '$'), '') if source_path: object_path = package elif package == _TOTAL_NODE_NAME:
diff --git a/tools/binary_size/libsupersize/diff.py b/tools/binary_size/libsupersize/diff.py index 47e42f1..09aafe43e 100644 --- a/tools/binary_size/libsupersize/diff.py +++ b/tools/binary_size/libsupersize/diff.py
@@ -25,6 +25,7 @@ name = _STRIP_NUMBERS_PATTERN.sub('', s.full_name) # Prefer source_path over object_path since object_path for native files have # the target_name in it (which can get renamed). + # Also because object_path of Java lambdas symbols contains a hash. path = s.source_path or s.object_path # Use section rather than section_name since clang & gcc use # .data.rel.ro vs. .data.rel.ro.local.
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden index 85e22d6..8b15dab 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
@@ -51,15 +51,15 @@ * 6 have a component assigned. Accounts for 524520 bytes (100.0%). * 0 symbols have shared ownership. * 3 symbols are from generated sources. Accounts for 232 bytes (0.0%). -Section .dex: has 100.0% of 8365003 bytes accounted for from 93 symbols. 0 bytes are unaccounted for. +Section .dex: has 100.0% of 8364863 bytes accounted for from 100 symbols. 0 bytes are unaccounted for. * Padding accounts for 0 bytes (0.0%) -* 83 have source paths. Accounts for 926 bytes (0.0%). +* 90 have source paths. Accounts for 1806 bytes (0.0%). * 0 have a component assigned. Accounts for 0 bytes (0.0%). * 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%). * 0 symbols have shared ownership. -Section .dex.method: has 100.0% of 23605 bytes accounted for from 100 symbols. 0 bytes are unaccounted for. +Section .dex.method: has 100.0% of 23745 bytes accounted for from 104 symbols. 0 bytes are unaccounted for. * Padding accounts for 0 bytes (0.0%) -* 90 have source paths. Accounts for 21154 bytes (89.6%). +* 94 have source paths. Accounts for 21294 bytes (89.7%). * 0 have a component assigned. Accounts for 0 bytes (0.0%). * 0 symbols have shared ownership. Section .pak.translations: has 100.0% of 6821 bytes accounted for from 208 symbols. 0 bytes are unaccounted for. @@ -180,7 +180,14 @@ .dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mWidth: float,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .dex@0(size_without_padding=104,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) -.dex@0(size_without_padding=8586,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=7566,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=23896,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=58449,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts,object_path=$APK/org/chromium/chrome/browser/compositor/layouts,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=111986,padding=0,full_name=org.chromium.chrome.browser.compositor,object_path=$APK/org/chromium/chrome/browser/compositor,source_path=,flags={},num_aliases=1,component=) @@ -289,6 +296,10 @@ .dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) .dex.method@0(size_without_padding=54,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) .dex.method@0(size_without_padding=52,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .other@0(size_without_padding=60,padding=0,full_name=** ELF Section: .ARM.attributes,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=28,padding=0,full_name=** ELF Section: .note.gnu.gold-version,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=436,padding=0,full_name=** ELF Section: .shstrtab,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden index 76239933..c77aa61 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
@@ -52,15 +52,15 @@ * 6 have a component assigned. Accounts for 524520 bytes (100.0%). * 0 symbols have shared ownership. * 3 symbols are from generated sources. Accounts for 232 bytes (0.0%). -Section .dex: has 100.0% of 8365003 bytes accounted for from 93 symbols. 0 bytes are unaccounted for. +Section .dex: has 100.0% of 8364863 bytes accounted for from 100 symbols. 0 bytes are unaccounted for. * Padding accounts for 0 bytes (0.0%) -* 83 have source paths. Accounts for 926 bytes (0.0%). +* 90 have source paths. Accounts for 1806 bytes (0.0%). * 0 have a component assigned. Accounts for 0 bytes (0.0%). * 1 placeholders exist (symbols that start with **). Accounts for 4616803 bytes (55.2%). * 0 symbols have shared ownership. -Section .dex.method: has 100.0% of 23605 bytes accounted for from 100 symbols. 0 bytes are unaccounted for. +Section .dex.method: has 100.0% of 23745 bytes accounted for from 104 symbols. 0 bytes are unaccounted for. * Padding accounts for 0 bytes (0.0%) -* 90 have source paths. Accounts for 21154 bytes (89.6%). +* 94 have source paths. Accounts for 21294 bytes (89.7%). * 0 have a component assigned. Accounts for 0 bytes (0.0%). * 0 symbols have shared ownership. Section .pak.translations: has 100.0% of 6821 bytes accounted for from 208 symbols. 0 bytes are unaccounted for. @@ -181,7 +181,14 @@ .dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation#mWidth: float,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .dex@0(size_without_padding=40,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .dex@0(size_without_padding=104,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) -.dex@0(size_without_padding=8586,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=220,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=10,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#$instance: Object,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=210,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0,object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex@0(size_without_padding=7566,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=23896,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=58449,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts,object_path=$APK/org/chromium/chrome/browser/compositor/layouts,source_path=,flags={},num_aliases=1,component=) .dex@0(size_without_padding=111986,padding=0,full_name=org.chromium.chrome.browser.compositor,object_path=$APK/org/chromium/chrome/browser/compositor,source_path=,flags={},num_aliases=1,component=) @@ -290,6 +297,10 @@ .dex.method@0(size_without_padding=79,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) .dex.method@0(size_without_padding=54,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#getScreenSizeInScrollDirection(): float,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) .dex.method@0(size_without_padding=52,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape#isDefaultDiscardDirectionPositive(): boolean,object_path=$APK/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimationLandscape,source_path=,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested1$$Lambda$1#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$Nested2$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) +.dex.method@0(size_without_padding=35,padding=0,full_name=org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation$$Lambda$0#<init>(),object_path=org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex,source_path=chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java,flags={},num_aliases=1,component=) .other@0(size_without_padding=60,padding=0,full_name=** ELF Section: .ARM.attributes,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=28,padding=0,full_name=** ELF Section: .note.gnu.gold-version,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=436,padding=0,full_name=** ELF Section: .shstrtab,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output b/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output index 6197c60c..822a9b4 100644 --- a/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output +++ b/tools/binary_size/libsupersize/testdata/mock_sdk/tools/bin/apkanalyzer.output
@@ -191,3 +191,14 @@ M d 1 1 79 org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape float getScreenPositionInScrollDirection(org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab) M d 1 1 54 org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape float getScreenSizeInScrollDirection() M d 1 1 52 org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimationLandscape boolean isDefaultDiscardDirectionPositive() +C d 10 12 255 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex +M d 1 1 35 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>() +F d 0 0 10 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance +C d 10 12 255 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex +M d 1 1 35 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested1$kjevdDQ8V2zqCrdieLqWLHzkB.dex <init>() +C d 10 12 255 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex +M d 1 1 35 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>() +F d 0 0 10 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$Nested2$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance +C d 10 12 255 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex +M d 1 1 35 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex <init>() +F d 0 0 10 org.chromium.chrome.browser.compositor.layouts.phone.stack.-$$Lambda$StackAnimation$kjevdDQ8V2zqCrdieLqWLHzk.dex Object $instance
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py index f7e984d8..293558ade 100755 --- a/tools/clang/scripts/build.py +++ b/tools/clang/scripts/build.py
@@ -473,6 +473,13 @@ '-DLLVM_INCLUDE_GO_TESTS=OFF', ] + if sys.platform == 'darwin': + # For libc++, we only want the headers. + base_cmake_args.extend([ + '-DLIBCXX_ENABLE_SHARED=OFF', '-DLIBCXX_ENABLE_STATIC=OFF', + '-DLIBCXX_INCLUDE_TESTS=OFF' + ]) + if args.gcc_toolchain: # Don't use the custom gcc toolchain when building compiler-rt tests; those # tests are built with the just-built Clang, and target both i386 and x86_64 @@ -489,12 +496,6 @@ cxxflags.append('-I' + zlib_dir) ldflags.append('-LIBPATH:' + zlib_dir) - if sys.platform == 'darwin': - # Use the system libc++abi. - # TODO(hans): use https://reviews.llvm.org/D62060 instead - base_cmake_args.append('-DLIBCXX_CXX_ABI=libcxxabi') - base_cmake_args.append('-DLIBCXX_CXX_ABI_SYSTEM=1') - if sys.platform != 'win32': # libxml2 is required by the Win manifest merging tool used in cross-builds. base_cmake_args.append('-DLLVM_ENABLE_LIBXML2=FORCE_ON')
diff --git a/tools/licenses.py b/tools/licenses.py index b61ee97..feeaf77 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -365,173 +365,175 @@ class LicenseError(Exception): - """We raise this exception when a directory's licensing info isn't + """We raise this exception when a directory's licensing info isn't fully filled out.""" - pass + pass + def AbsolutePath(path, filename, root): - """Convert a path in README.chromium to be absolute based on the source + """Convert a path in README.chromium to be absolute based on the source root.""" - if filename.startswith('/'): - # Absolute-looking paths are relative to the source root - # (which is the directory we're run from). - absolute_path = os.path.join(root, filename[1:]) - else: - absolute_path = os.path.join(root, path, filename) - if os.path.exists(absolute_path): - return absolute_path - return None + if filename.startswith('/'): + # Absolute-looking paths are relative to the source root + # (which is the directory we're run from). + absolute_path = os.path.join(root, filename[1:]) + else: + absolute_path = os.path.join(root, path, filename) + if os.path.exists(absolute_path): + return absolute_path + return None + def ParseDir(path, root, require_license_file=True, optional_keys=None): - """Examine a third_party/foo component and extract its metadata.""" - # Parse metadata fields out of README.chromium. - # We examine "LICENSE" for the license file by default. - metadata = { - "License File": "LICENSE", # Relative path to license text. - "Name": None, # Short name (for header on about:credits). - "URL": None, # Project home page. - "License": None, # Software license. - } + """Examine a third_party/foo component and extract its metadata.""" + # Parse metadata fields out of README.chromium. + # We examine "LICENSE" for the license file by default. + metadata = { + "License File": "LICENSE", # Relative path to license text. + "Name": None, # Short name (for header on about:credits). + "URL": None, # Project home page. + "License": None, # Software license. + } - if optional_keys is None: - optional_keys = [] + if optional_keys is None: + optional_keys = [] - if path in SPECIAL_CASES: - metadata.update(SPECIAL_CASES[path]) - else: - # Try to find README.chromium. - readme_path = os.path.join(root, path, 'README.chromium') - if not os.path.exists(readme_path): - raise LicenseError("missing README.chromium or licenses.py " - "SPECIAL_CASES entry in %s\n" % path) + if path in SPECIAL_CASES: + metadata.update(SPECIAL_CASES[path]) + else: + # Try to find README.chromium. + readme_path = os.path.join(root, path, 'README.chromium') + if not os.path.exists(readme_path): + raise LicenseError("missing README.chromium or licenses.py " + "SPECIAL_CASES entry in %s\n" % path) - for line in open(readme_path): - line = line.strip() - if not line: - break - for key in list(metadata.keys()) + optional_keys: - field = key + ": " - if line.startswith(field): - metadata[key] = line[len(field):] + for line in open(readme_path): + line = line.strip() + if not line: + break + for key in list(metadata.keys()) + optional_keys: + field = key + ": " + if line.startswith(field): + metadata[key] = line[len(field):] - # Check that all expected metadata is present. - errors = [] - for key, value in metadata.items(): - if not value: - errors.append("couldn't find '" + key + "' line " - "in README.chromium or licences.py " - "SPECIAL_CASES") + # Check that all expected metadata is present. + errors = [] + for key, value in metadata.items(): + if not value: + errors.append("couldn't find '" + key + "' line " + "in README.chromium or licences.py " + "SPECIAL_CASES") - # Special-case modules that aren't in the shipping product, so don't need - # their license in about:credits. - if metadata["License File"] != NOT_SHIPPED: - # Check that the license file exists. - for filename in (metadata["License File"], "COPYING"): - license_path = AbsolutePath(path, filename, root) - if license_path is not None: - break + # Special-case modules that aren't in the shipping product, so don't need + # their license in about:credits. + if metadata["License File"] != NOT_SHIPPED: + # Check that the license file exists. + for filename in (metadata["License File"], "COPYING"): + license_path = AbsolutePath(path, filename, root) + if license_path is not None: + break - if require_license_file and not license_path: - errors.append("License file not found. " - "Either add a file named LICENSE, " - "import upstream's COPYING if available, " - "or add a 'License File:' line to " - "README.chromium with the appropriate path.") - metadata["License File"] = license_path + if require_license_file and not license_path: + errors.append("License file not found. " + "Either add a file named LICENSE, " + "import upstream's COPYING if available, " + "or add a 'License File:' line to " + "README.chromium with the appropriate path.") + metadata["License File"] = license_path - if errors: - raise LicenseError("Errors in %s:\n %s\n" % (path, ";\n ".join(errors))) - return metadata + if errors: + raise LicenseError("Errors in %s:\n %s\n" % (path, ";\n ".join(errors))) + return metadata def ContainsFiles(path, root): - """Determines whether any files exist in a directory or in any of its + """Determines whether any files exist in a directory or in any of its subdirectories.""" - for _, dirs, files in os.walk(os.path.join(root, path)): - if files: - return True - for vcs_metadata in VCS_METADATA_DIRS: - if vcs_metadata in dirs: - dirs.remove(vcs_metadata) - return False + for _, dirs, files in os.walk(os.path.join(root, path)): + if files: + return True + for vcs_metadata in VCS_METADATA_DIRS: + if vcs_metadata in dirs: + dirs.remove(vcs_metadata) + return False def FilterDirsWithFiles(dirs_list, root): - # If a directory contains no files, assume it's a DEPS directory for a - # project not used by our current configuration and skip it. - return [x for x in dirs_list if ContainsFiles(x, root)] + # If a directory contains no files, assume it's a DEPS directory for a + # project not used by our current configuration and skip it. + return [x for x in dirs_list if ContainsFiles(x, root)] def FindThirdPartyDirs(prune_paths, root): - """Find all third_party directories underneath the source root.""" - third_party_dirs = set() - for path, dirs, files in os.walk(root): - path = path[len(root)+1:] # Pretty up the path. + """Find all third_party directories underneath the source root.""" + third_party_dirs = set() + for path, dirs, files in os.walk(root): + path = path[len(root) + 1:] # Pretty up the path. - if path in prune_paths: - dirs[:] = [] - continue + if path in prune_paths: + dirs[:] = [] + continue - # Prune out directories we want to skip. - # (Note that we loop over PRUNE_DIRS so we're not iterating over a - # list that we're simultaneously mutating.) - for skip in PRUNE_DIRS: - if skip in dirs: - dirs.remove(skip) + # Prune out directories we want to skip. + # (Note that we loop over PRUNE_DIRS so we're not iterating over a + # list that we're simultaneously mutating.) + for skip in PRUNE_DIRS: + if skip in dirs: + dirs.remove(skip) - if os.path.basename(path) == 'third_party': - # Add all subdirectories that are not marked for skipping. - for dir in dirs: - dirpath = os.path.join(path, dir) - additional_paths_file = os.path.join( - root, dirpath, ADDITIONAL_PATHS_FILENAME) - if dirpath not in prune_paths: - third_party_dirs.add(dirpath) - if os.path.exists(additional_paths_file): - with open(additional_paths_file) as paths_file: - extra_paths = json.load(paths_file) - third_party_dirs.update([ - os.path.join(dirpath, p) for p in extra_paths]) + if os.path.basename(path) == 'third_party': + # Add all subdirectories that are not marked for skipping. + for dir in dirs: + dirpath = os.path.join(path, dir) + additional_paths_file = os.path.join(root, dirpath, + ADDITIONAL_PATHS_FILENAME) + if dirpath not in prune_paths: + third_party_dirs.add(dirpath) + if os.path.exists(additional_paths_file): + with open(additional_paths_file) as paths_file: + extra_paths = json.load(paths_file) + third_party_dirs.update( + [os.path.join(dirpath, p) for p in extra_paths]) - # Don't recurse into any subdirs from here. - dirs[:] = [] - continue + # Don't recurse into any subdirs from here. + dirs[:] = [] + continue - # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular - # third_party/foo paths. - if path in ADDITIONAL_PATHS: - dirs[:] = [] + # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular + # third_party/foo paths. + if path in ADDITIONAL_PATHS: + dirs[:] = [] - for dir in ADDITIONAL_PATHS: - if dir not in prune_paths: - third_party_dirs.add(dir) + for dir in ADDITIONAL_PATHS: + if dir not in prune_paths: + third_party_dirs.add(dir) - return third_party_dirs + return third_party_dirs def FindThirdPartyDirsWithFiles(root): - third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, root) - return FilterDirsWithFiles(third_party_dirs, root) + third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, root) + return FilterDirsWithFiles(third_party_dirs, root) # Many builders do not contain 'gn' in their PATH, so use the GN binary from # //buildtools. def _GnBinary(): - exe = 'gn' - if sys.platform.startswith('linux'): - subdir = 'linux64' - elif sys.platform == 'darwin': - subdir = 'mac' - elif sys.platform == 'win32': - subdir, exe = 'win', 'gn.exe' - else: - raise RuntimeError("Unsupported platform '%s'." % sys.platform) + exe = 'gn' + if sys.platform.startswith('linux'): + subdir = 'linux64' + elif sys.platform == 'darwin': + subdir = 'mac' + elif sys.platform == 'win32': + subdir, exe = 'win', 'gn.exe' + else: + raise RuntimeError("Unsupported platform '%s'." % sys.platform) - return os.path.join(_REPOSITORY_ROOT, 'buildtools', subdir, exe) + return os.path.join(_REPOSITORY_ROOT, 'buildtools', subdir, exe) def GetThirdPartyDepsFromGNDepsOutput(gn_deps, target_os): - """Returns third_party/foo directories given the output of "gn desc deps". + """Returns third_party/foo directories given the output of "gn desc deps". Note that it always returns the direct sub-directory of third_party where README.chromium and LICENSE files are, so that it can be passed to @@ -540,269 +542,265 @@ It returns relative paths from _REPOSITORY_ROOT, not absolute paths. """ - third_party_deps = set() - for absolute_build_dep in gn_deps.split(): - relative_build_dep = os.path.relpath( - absolute_build_dep, _REPOSITORY_ROOT) - m = re.search( - r'^((.+[/\\])?third_party[/\\][^/\\]+[/\\])(.+[/\\])?BUILD\.gn$', - relative_build_dep) - if not m: - continue - third_party_path = m.group(1) - if any(third_party_path.startswith(p + os.sep) for p in PRUNE_PATHS): - continue - if (target_os == 'ios' and - any(third_party_path.startswith(p + os.sep) - for p in KNOWN_NON_IOS_LIBRARIES)): - # Skip over files that are known not to be used on iOS. - continue - third_party_deps.add(third_party_path[:-1]) - return third_party_deps + third_party_deps = set() + for absolute_build_dep in gn_deps.split(): + relative_build_dep = os.path.relpath(absolute_build_dep, _REPOSITORY_ROOT) + m = re.search( + r'^((.+[/\\])?third_party[/\\][^/\\]+[/\\])(.+[/\\])?BUILD\.gn$', + relative_build_dep) + if not m: + continue + third_party_path = m.group(1) + if any(third_party_path.startswith(p + os.sep) for p in PRUNE_PATHS): + continue + if (target_os == 'ios' and any( + third_party_path.startswith(p + os.sep) + for p in KNOWN_NON_IOS_LIBRARIES)): + # Skip over files that are known not to be used on iOS. + continue + third_party_deps.add(third_party_path[:-1]) + return third_party_deps def FindThirdPartyDeps(gn_out_dir, gn_target, target_os): - if not gn_out_dir: - raise RuntimeError("--gn-out-dir is required if --gn-target is used.") + if not gn_out_dir: + raise RuntimeError("--gn-out-dir is required if --gn-target is used.") - # Generate gn project in temp directory and use it to find dependencies. - # Current gn directory cannot be used when we run this script in a gn action - # rule, because gn doesn't allow recursive invocations due to potential side - # effects. - tmp_dir = None - try: - tmp_dir = tempfile.mkdtemp(dir = gn_out_dir) - shutil.copy(os.path.join(gn_out_dir, "args.gn"), tmp_dir) - subprocess.check_output([_GnBinary(), "gen", tmp_dir]) - gn_deps = subprocess.check_output([ - _GnBinary(), "desc", tmp_dir, gn_target, - "deps", "--as=buildfile", "--all"]) - if isinstance(gn_deps, bytes): - gn_deps = gn_deps.decode("utf-8") - finally: - if tmp_dir and os.path.exists(tmp_dir): - shutil.rmtree(tmp_dir) + # Generate gn project in temp directory and use it to find dependencies. + # Current gn directory cannot be used when we run this script in a gn action + # rule, because gn doesn't allow recursive invocations due to potential side + # effects. + tmp_dir = None + try: + tmp_dir = tempfile.mkdtemp(dir=gn_out_dir) + shutil.copy(os.path.join(gn_out_dir, "args.gn"), tmp_dir) + subprocess.check_output([_GnBinary(), "gen", tmp_dir]) + gn_deps = subprocess.check_output([ + _GnBinary(), "desc", tmp_dir, gn_target, "deps", "--as=buildfile", + "--all" + ]) + if isinstance(gn_deps, bytes): + gn_deps = gn_deps.decode("utf-8") + finally: + if tmp_dir and os.path.exists(tmp_dir): + shutil.rmtree(tmp_dir) - return GetThirdPartyDepsFromGNDepsOutput(gn_deps, target_os) + return GetThirdPartyDepsFromGNDepsOutput(gn_deps, target_os) def ScanThirdPartyDirs(root=None): - """Scan a list of directories and report on any problems we find.""" - if root is None: - root = os.getcwd() - third_party_dirs = FindThirdPartyDirsWithFiles(root) + """Scan a list of directories and report on any problems we find.""" + if root is None: + root = os.getcwd() + third_party_dirs = FindThirdPartyDirsWithFiles(root) - errors = [] - for path in sorted(third_party_dirs): - try: - metadata = ParseDir(path, root) - except LicenseError as e: - errors.append((path, e.args[0])) - continue + errors = [] + for path in sorted(third_party_dirs): + try: + metadata = ParseDir(path, root) + except LicenseError as e: + errors.append((path, e.args[0])) + continue - for path, error in sorted(errors): - print(path + ": " + error) + for path, error in sorted(errors): + print(path + ": " + error) - return len(errors) == 0 + return len(errors) == 0 def GenerateCredits( file_template_file, entry_template_file, output_file, target_os, gn_out_dir, gn_target, depfile=None): - """Generate about:credits.""" + """Generate about:credits.""" - def EvaluateTemplate(template, env, escape=True): - """Expand a template with variables like {{foo}} using a + def EvaluateTemplate(template, env, escape=True): + """Expand a template with variables like {{foo}} using a dictionary of expansions.""" - for key, val in env.items(): - if escape: - val = html.escape(val) - template = template.replace('{{%s}}' % key, val) - return template + for key, val in env.items(): + if escape: + val = html.escape(val) + template = template.replace('{{%s}}' % key, val) + return template - def MetadataToTemplateEntry(metadata, entry_template): - env = { - 'name': metadata['Name'], - 'url': metadata['URL'], - 'license': open(metadata['License File']).read(), - } - return { - 'name': metadata['Name'], - 'content': EvaluateTemplate(entry_template, env), - 'license_file': metadata['License File'], - } + def MetadataToTemplateEntry(metadata, entry_template): + env = { + 'name': metadata['Name'], + 'url': metadata['URL'], + 'license': open(metadata['License File']).read(), + } + return { + 'name': metadata['Name'], + 'content': EvaluateTemplate(entry_template, env), + 'license_file': metadata['License File'], + } - if gn_target: - third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os) + if gn_target: + third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os) - # Sanity-check to raise a build error if invalid gn_... settings are - # somehow passed to this script. - if not third_party_dirs: - raise RuntimeError("No deps found.") - else: - third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, _REPOSITORY_ROOT) + # Sanity-check to raise a build error if invalid gn_... settings are + # somehow passed to this script. + if not third_party_dirs: + raise RuntimeError("No deps found.") + else: + third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, _REPOSITORY_ROOT) - if not file_template_file: - file_template_file = os.path.join(_REPOSITORY_ROOT, 'components', - 'about_ui', 'resources', - 'about_credits.tmpl') - if not entry_template_file: - entry_template_file = os.path.join(_REPOSITORY_ROOT, 'components', - 'about_ui', 'resources', - 'about_credits_entry.tmpl') + if not file_template_file: + file_template_file = os.path.join(_REPOSITORY_ROOT, 'components', + 'about_ui', 'resources', + 'about_credits.tmpl') + if not entry_template_file: + entry_template_file = os.path.join(_REPOSITORY_ROOT, 'components', + 'about_ui', 'resources', + 'about_credits_entry.tmpl') - entry_template = open(entry_template_file).read() - entries = [] - # Start from Chromium's LICENSE file - chromium_license_metadata = { - 'Name': 'The Chromium Project', - 'URL': 'http://www.chromium.org', - 'License File': os.path.join(_REPOSITORY_ROOT, 'LICENSE') } - entries.append(MetadataToTemplateEntry(chromium_license_metadata, - entry_template)) + entry_template = open(entry_template_file).read() + entries = [] + # Start from Chromium's LICENSE file + chromium_license_metadata = { + 'Name': 'The Chromium Project', + 'URL': 'http://www.chromium.org', + 'License File': os.path.join(_REPOSITORY_ROOT, 'LICENSE') + } + entries.append( + MetadataToTemplateEntry(chromium_license_metadata, entry_template)) - for path in third_party_dirs: - try: - metadata = ParseDir(path, _REPOSITORY_ROOT) - except LicenseError: - # TODO(phajdan.jr): Convert to fatal error (http://crbug.com/39240). - continue - if metadata['License File'] == NOT_SHIPPED: - continue - if target_os == 'ios' and not gn_target: - # Skip over files that are known not to be used on iOS. But - # skipping is unnecessary if GN was used to query the actual - # dependencies. - # TODO(lambroslambrou): Remove this step once the iOS build is - # updated to provide --gn-target to this script. - if path in KNOWN_NON_IOS_LIBRARIES: - continue - entries.append(MetadataToTemplateEntry(metadata, entry_template)) + for path in third_party_dirs: + try: + metadata = ParseDir(path, _REPOSITORY_ROOT) + except LicenseError: + # TODO(phajdan.jr): Convert to fatal error (http://crbug.com/39240). + continue + if metadata['License File'] == NOT_SHIPPED: + continue + if target_os == 'ios' and not gn_target: + # Skip over files that are known not to be used on iOS. But + # skipping is unnecessary if GN was used to query the actual + # dependencies. + # TODO(lambroslambrou): Remove this step once the iOS build is + # updated to provide --gn-target to this script. + if path in KNOWN_NON_IOS_LIBRARIES: + continue + entries.append(MetadataToTemplateEntry(metadata, entry_template)) - entries.sort(key=lambda entry: (entry['name'].lower(), entry['content'])) - for entry_id, entry in enumerate(entries): - entry['content'] = entry['content'].replace('{{id}}', str(entry_id)) + entries.sort(key=lambda entry: (entry['name'].lower(), entry['content'])) + for entry_id, entry in enumerate(entries): + entry['content'] = entry['content'].replace('{{id}}', str(entry_id)) - entries_contents = '\n'.join([entry['content'] for entry in entries]) - file_template = open(file_template_file).read() - template_contents = "<!-- Generated by licenses.py; do not edit. -->" - template_contents += EvaluateTemplate(file_template, - {'entries': entries_contents}, - escape=False) + entries_contents = '\n'.join([entry['content'] for entry in entries]) + file_template = open(file_template_file).read() + template_contents = "<!-- Generated by licenses.py; do not edit. -->" + template_contents += EvaluateTemplate( + file_template, {'entries': entries_contents}, escape=False) - if output_file: - changed = True - try: - old_output = open(output_file, 'r').read() - if old_output == template_contents: - changed = False - except: - pass - if changed: - with open(output_file, 'w') as output: - output.write(template_contents) - else: - print(template_contents) + if output_file: + changed = True + try: + old_output = open(output_file, 'r').read() + if old_output == template_contents: + changed = False + except: + pass + if changed: + with open(output_file, 'w') as output: + output.write(template_contents) + else: + print(template_contents) - if depfile: - assert output_file - # Add in build.ninja so that the target will be considered dirty whenever - # gn gen is run. Otherwise, it will fail to notice new files being added. - # This is still no perfect, as it will fail if no build files are changed, - # but a new README.chromium / LICENSE is added. This shouldn't happen in - # practice however. - license_file_list = (entry['license_file'] for entry in entries) - license_file_list = (os.path.relpath(p) for p in license_file_list) - license_file_list = sorted(set(license_file_list)) - build_utils.WriteDepfile(depfile, output_file, - license_file_list + ['build.ninja']) + if depfile: + assert output_file + # Add in build.ninja so that the target will be considered dirty whenever + # gn gen is run. Otherwise, it will fail to notice new files being added. + # This is still no perfect, as it will fail if no build files are changed, + # but a new README.chromium / LICENSE is added. This shouldn't happen in + # practice however. + license_file_list = (entry['license_file'] for entry in entries) + license_file_list = (os.path.relpath(p) for p in license_file_list) + license_file_list = sorted(set(license_file_list)) + build_utils.WriteDepfile(depfile, output_file, + license_file_list + ['build.ninja']) - return True + return True def _ReadFile(path): - """Reads a file from disk. + """Reads a file from disk. Args: path: The path of the file to read, relative to the root of the repository. Returns: The contents of the file as a string. """ - with codecs.open(os.path.join(_REPOSITORY_ROOT, path), 'r', 'utf-8') as f: - return f.read() + with codecs.open(os.path.join(_REPOSITORY_ROOT, path), 'r', 'utf-8') as f: + return f.read() def GenerateLicenseFile(output_file, gn_out_dir, gn_target, target_os): - """Generate a plain-text LICENSE file which can be used when you ship a part + """Generate a plain-text LICENSE file which can be used when you ship a part of Chromium code (specified by gn_target) as a stand-alone library (e.g., //ios/web_view). The LICENSE file contains licenses of both Chromium and third-party libraries which gn_target depends on. """ - third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os) + third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target, target_os) - # Start with Chromium's LICENSE file. - content = [_ReadFile('LICENSE')] + # Start with Chromium's LICENSE file. + content = [_ReadFile('LICENSE')] - # Add necessary third_party. - for directory in sorted(third_party_dirs): - metadata = ParseDir( - directory, _REPOSITORY_ROOT, require_license_file=True) - content.append('-' * 20) - content.append(directory.split(os.sep)[-1]) - content.append('-' * 20) - license_file = metadata['License File'] - if license_file and license_file != NOT_SHIPPED: - content.append(_ReadFile(license_file)) + # Add necessary third_party. + for directory in sorted(third_party_dirs): + metadata = ParseDir(directory, _REPOSITORY_ROOT, require_license_file=True) + content.append('-' * 20) + content.append(directory.split(os.sep)[-1]) + content.append('-' * 20) + license_file = metadata['License File'] + if license_file and license_file != NOT_SHIPPED: + content.append(_ReadFile(license_file)) - content_text = '\n'.join(content) + content_text = '\n'.join(content) - if output_file: - with codecs.open(output_file, 'w', 'utf-8') as output: - output.write(content_text) - else: - print(content_text) + if output_file: + with codecs.open(output_file, 'w', 'utf-8') as output: + output.write(content_text) + else: + print(content_text) def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--file-template', - help='Template HTML to use for the license page.') - parser.add_argument('--entry-template', - help='Template HTML to use for each license.') - parser.add_argument('--target-os', - help='OS that this build is targeting.') - parser.add_argument('--gn-out-dir', - help='GN output directory for scanning dependencies.') - parser.add_argument('--gn-target', - help='GN target to scan for dependencies.') - parser.add_argument('command', - choices=['help', 'scan', 'credits', 'license_file']) - parser.add_argument('output_file', nargs='?') - build_utils.AddDepfileOption(parser) - args = parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument( + '--file-template', help='Template HTML to use for the license page.') + parser.add_argument( + '--entry-template', help='Template HTML to use for each license.') + parser.add_argument('--target-os', help='OS that this build is targeting.') + parser.add_argument( + '--gn-out-dir', help='GN output directory for scanning dependencies.') + parser.add_argument('--gn-target', help='GN target to scan for dependencies.') + parser.add_argument( + 'command', choices=['help', 'scan', 'credits', 'license_file']) + parser.add_argument('output_file', nargs='?') + build_utils.AddDepfileOption(parser) + args = parser.parse_args() - if args.command == 'scan': - if not ScanThirdPartyDirs(): - return 1 - elif args.command == 'credits': - if not GenerateCredits(args.file_template, args.entry_template, - args.output_file, args.target_os, - args.gn_out_dir, args.gn_target, args.depfile): - return 1 - elif args.command == 'license_file': - try: - GenerateLicenseFile( - args.output_file, args.gn_out_dir, args.gn_target, - args.target_os) - except LicenseError as e: - print("Failed to parse README.chromium: {}".format(e)) - return 1 - else: - print(__doc__) - return 1 + if args.command == 'scan': + if not ScanThirdPartyDirs(): + return 1 + elif args.command == 'credits': + if not GenerateCredits(args.file_template, args.entry_template, + args.output_file, args.target_os, args.gn_out_dir, + args.gn_target, args.depfile): + return 1 + elif args.command == 'license_file': + try: + GenerateLicenseFile(args.output_file, args.gn_out_dir, args.gn_target, + args.target_os) + except LicenseError as e: + print("Failed to parse README.chromium: {}".format(e)) + return 1 + else: + print(__doc__) + return 1 if __name__ == '__main__':
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d2805db..aaecf6f0 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -26576,7 +26576,7 @@ <int value="2887" label="V8RTCRtpReceiver_JitterBufferDelayHint_AttributeSetter"/> <int value="2888" label="MediaCapabilitiesDecodingInfoWithKeySystemConfig"/> - <int value="2889" label="RevertInCustomIdent"/> + <int value="2889" label="OBSOLETE_RevertInCustomIdent"/> <int value="2890" label="UnoptimizedImagePolicies"/> <int value="2891" label="VTTCueParser"/> <int value="2892" label="MediaElementTextTrackContainer"/> @@ -26899,6 +26899,7 @@ <int value="3198" label="CrossOriginOpenerPolicySameOriginAllowPopups"/> <int value="3199" label="CrossOriginEmbedderPolicyRequireCorp"/> <int value="3200" label="CoopAndCoepIsolated"/> + <int value="3201" label="WrongBaselineOfButtonElement"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -33106,6 +33107,23 @@ <int value="20" label="Duplicate entry"/> </enum> +<enum name="ICUCreateInstanceCode"> + <summary>Recorded when ICU create instance of key objects.</summary> + <int value="0" label="Character Break Iterator"/> + <int value="1" label="Word Break Iterator"/> + <int value="2" label="Line Break Iterator"/> + <int value="3" label="Line Break Iterator (type=loose)"/> + <int value="4" label="Line Break Iterator (type=normal)"/> + <int value="5" label="Line Break Iterator (type=strict)"/> + <int value="6" label="Sentence Break Iterator"/> + <int value="7" label="Title Break Iterator"/> + <int value="8" label="Thai Break Engine"/> + <int value="9" label="Lao Break Engine"/> + <int value="10" label="Burmese Break Engine"/> + <int value="11" label="Khmer Break Engine"/> + <int value="12" label="Chinese/Japanese Break Engine"/> +</enum> + <enum name="ICUDataFileCode"> <summary> Hash values for strings of the ICU built-in data file names. @@ -41994,7 +42012,7 @@ <int value="172" label="alias-webkit-animation-name"/> <int value="173" label="alias-webkit-animation-play-state"/> <int value="174" label="alias-webkit-animation-timing-function"/> - <int value="175" label="webkit-appearance"/> + <int value="175" label="alias-webkit-appearance"/> <int value="176" label="webkit-aspect-ratio"/> <int value="177" label="alias-webkit-backface-visibility"/> <int value="178" label="alias-webkit-background-clip"/> @@ -42477,6 +42495,7 @@ <int value="655" label="subtree-visibility"/> <int value="656" label="math-style"/> <int value="657" label="aspect-ratio"/> + <int value="658" label="appearance"/> </enum> <enum name="MappedEditingCommands"> @@ -50233,6 +50252,9 @@ </enum> <enum name="PasswordGenerationPresaveConflict"> + <obsolete> + Deprecated as of 2020-04. + </obsolete> <int value="0" label="No username conflict"/> <int value="1" label="No conflict with empty username"/> <int value="2" label="Conflict with empty username"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b8ff2fb..b70dd3f 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -56558,7 +56558,7 @@ </histogram> <histogram name="FCMInvalidations.ResetClientIDStatus" enum="InstanceIDResult" - expires_after="M83"> + expires_after="M85"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -58578,7 +58578,10 @@ </histogram> <histogram name="GCM.GetInstanceIDData.ClientStarted" enum="GCMClientResult" - expires_after="M83"> + expires_after="2020-04-02"> + <obsolete> + Removed in April 2020. + </obsolete> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -58598,7 +58601,7 @@ </histogram> <histogram base="true" name="GCM.IgnoredWriteResult" enum="BooleanSuccess" - expires_after="M83"> + expires_after="M85"> <!-- Name completed by histogram_suffixes name="IgnoredWriteResultOperation" --> <owner>tschumann@chromium.org</owner> @@ -58606,8 +58609,8 @@ <summary> Result of the outcome of persisting a change in the GCMStore. This histogram is to meausure the frequency of such events and assess their severity. For - example, failing to write when calling AdddInstanceIDData() likely results - in leaked FCM registrations. + example, failing to write when calling AddInstanceIDData() likely results in + leaked FCM registrations. </summary> </histogram> @@ -64225,6 +64228,17 @@ <summary>The time it takes to open a hyphenation dictionary file.</summary> </histogram> +<histogram name="ICU.CreateInstance" enum="ICUCreateInstanceCode" + expires_after="2020-10-15"> + <owner>ftang@chromium.org</owner> + <owner>intl-libs-team@google.com</owner> + <summary> + This metric logs the creation of key ICU objects. These object creation + called directly from Chrome code or indirectly from depending library such + as blink and v8. + </summary> +</histogram> + <histogram name="ICU.DataFile" enum="ICUDataFileCode" expires_after="2020-10-15"> <owner>ftang@chromium.org</owner> @@ -65889,7 +65903,7 @@ </histogram> <histogram name="InstanceID.GeneratedNewID" enum="BooleanHit" - expires_after="M83"> + expires_after="M85"> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -70646,8 +70660,9 @@ </histogram> <histogram name="Media.Audio.Capture.HighLatencyCallbackError" - enum="BooleanError" expires_after="2020-04-05"> - <owner>maxmorin@chromium.org</owner> + enum="BooleanError" expires_after="2021-04-05"> + <owner>guidou@chromium.org</owner> + <owner>olka@chromium.org</owner> <summary> A boolean that reflects whether or not an error was reported during audio capture for a high latency stream. @@ -70655,8 +70670,9 @@ </histogram> <histogram name="Media.Audio.Capture.InputStreamDuration" units="ms" - expires_after="M85"> - <owner>maxmorin@chromium.org</owner> + expires_after="2021-04-05"> + <owner>guidou@chromium.org</owner> + <owner>olka@chromium.org</owner> <summary> This histogram measures the duration of every input stream, as seen from the renderer. It counts from when it has been successfully started, until it is @@ -70688,8 +70704,9 @@ </histogram> <histogram name="Media.Audio.Capture.LowLatencyCallbackError" - enum="BooleanError" expires_after="2020-04-05"> - <owner>maxmorin@chromium.org</owner> + enum="BooleanError" expires_after="2021-04-05"> + <owner>guidou@chromium.org</owner> + <owner>olka@chromium.org</owner> <summary> A boolean that reflects whether or not an error was reported during audio capture for a low latency stream. @@ -114915,6 +114932,9 @@ <histogram name="PasswordGeneration.PresaveConflict" enum="PasswordGenerationPresaveConflict" expires_after="M83"> + <obsolete> + Removed 2020-04. + </obsolete> <owner>vasilii@chromium.org</owner> <owner>jdoerrie@chromium.org</owner> <summary> @@ -116967,6 +116987,9 @@ <histogram name="PasswordManager.PresavedUpdateUIDismissalReason" enum="PasswordManagerUIDismissalReason" expires_after="M83"> + <obsolete> + Removed 2020-04. + </obsolete> <owner>vasilii@chromium.org</owner> <owner>jdoerrie@chromium.org</owner> <summary> @@ -187814,6 +187837,7 @@ label="From app list query context menu."/> <suffix name="FromAppListRecommendation" label="From app list recommendation."/> + <suffix name="FromArc" label="From ARC."/> <suffix name="FromChromeInternal" label="From Chrome Internal."/> <suffix name="FromFileManager" label="From FileManager."/> <suffix name="FromInstalledNotification" @@ -199352,6 +199376,13 @@ <suffix name="PulseIntervalMedium" label="Medium pulse interval"/> <suffix name="PulseIntervalShort" label="Short pulse interval"/> <affected-histogram name="Sharing.SendMessageResult"/> + <affected-histogram name="Sharing.SendMessageResult.Android"/> + <affected-histogram name="Sharing.SendMessageResult.ChromeOS"/> + <affected-histogram name="Sharing.SendMessageResult.iOS"/> + <affected-histogram name="Sharing.SendMessageResult.Linux"/> + <affected-histogram name="Sharing.SendMessageResult.Mac"/> + <affected-histogram name="Sharing.SendMessageResult.Unknown"/> + <affected-histogram name="Sharing.SendMessageResult.Windows"/> </histogram_suffixes> <histogram_suffixes name="SharingSendMessageResult" separator=".">
diff --git a/ui/base/cocoa/text_services_context_menu.cc b/ui/base/cocoa/text_services_context_menu.cc index e4de932..d149dd8 100644 --- a/ui/base/cocoa/text_services_context_menu.cc +++ b/ui/base/cocoa/text_services_context_menu.cc
@@ -17,6 +17,22 @@ namespace { +enum MenuCommands { + // These must not overlap with the command IDs used by other menus that + // incorporate text services. + // TODO(ellyjones): This is an ugly global dependency, especially on + // //ui/views. What can we do about this? Can we get rid of the global + // implicit namespace of command IDs? + kSpeechMenu = 100, + kSpeechStartSpeaking, + kSpeechStopSpeaking, + + kWritingDirectionMenu, + kWritingDirectionDefault, + kWritingDirectionLtr, + kWritingDirectionRtl, +}; + // The speech channel used for speaking. This is shared to check if a speech // channel is currently speaking. SpeechChannel g_speech_channel; @@ -25,11 +41,11 @@ // |command_id|. base::i18n::TextDirection GetTextDirectionFromCommandId(int command_id) { switch (command_id) { - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: + case kWritingDirectionDefault: return base::i18n::UNKNOWN_DIRECTION; - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: + case kWritingDirectionLtr: return base::i18n::LEFT_TO_RIGHT; - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + case kWritingDirectionRtl: return base::i18n::RIGHT_TO_LEFT; default: NOTREACHED(); @@ -47,20 +63,17 @@ delegate_(delegate) { DCHECK(delegate); - speech_submenu_model_.AddItemWithStringId(IDS_SPEECH_START_SPEAKING_MAC, + speech_submenu_model_.AddItemWithStringId(kSpeechStartSpeaking, IDS_SPEECH_START_SPEAKING_MAC); - speech_submenu_model_.AddItemWithStringId(IDS_SPEECH_STOP_SPEAKING_MAC, + speech_submenu_model_.AddItemWithStringId(kSpeechStopSpeaking, IDS_SPEECH_STOP_SPEAKING_MAC); bidi_submenu_model_.AddCheckItemWithStringId( - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT, - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT); + kWritingDirectionDefault, IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT); bidi_submenu_model_.AddCheckItemWithStringId( - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR, - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR); + kWritingDirectionLtr, IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR); bidi_submenu_model_.AddCheckItemWithStringId( - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL, - IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL); + kWritingDirectionRtl, IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL); } void TextServicesContextMenu::SpeakText(const base::string16& text) { @@ -88,7 +101,7 @@ void TextServicesContextMenu::AppendToContextMenu(SimpleMenuModel* model) { model->AddSeparator(NORMAL_SEPARATOR); - model->AddSubMenuWithStringId(IDS_SPEECH_MAC, IDS_SPEECH_MAC, + model->AddSubMenuWithStringId(kSpeechMenu, IDS_SPEECH_MAC, &speech_submenu_model_); } @@ -96,20 +109,20 @@ // MacOS provides a contextual menu to set writing direction for BiDi // languages. This functionality is exposed as a keyboard shortcut on // Windows and Linux. - model->AddSubMenuWithStringId(IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU, + model->AddSubMenuWithStringId(kWritingDirectionMenu, IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU, &bidi_submenu_model_); } bool TextServicesContextMenu::SupportsCommand(int command_id) const { switch (command_id) { - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: - case IDS_SPEECH_MAC: - case IDS_SPEECH_START_SPEAKING_MAC: - case IDS_SPEECH_STOP_SPEAKING_MAC: + case kWritingDirectionMenu: + case kWritingDirectionDefault: + case kWritingDirectionLtr: + case kWritingDirectionRtl: + case kSpeechMenu: + case kSpeechStartSpeaking: + case kSpeechStopSpeaking: return true; } @@ -118,13 +131,13 @@ bool TextServicesContextMenu::IsCommandIdChecked(int command_id) const { switch (command_id) { - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + case kWritingDirectionDefault: + case kWritingDirectionLtr: + case kWritingDirectionRtl: return delegate_->IsTextDirectionChecked( GetTextDirectionFromCommandId(command_id)); - case IDS_SPEECH_START_SPEAKING_MAC: - case IDS_SPEECH_STOP_SPEAKING_MAC: + case kSpeechStartSpeaking: + case kSpeechStopSpeaking: return false; } @@ -134,17 +147,17 @@ bool TextServicesContextMenu::IsCommandIdEnabled(int command_id) const { switch (command_id) { - case IDS_SPEECH_MAC: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_MENU: + case kSpeechMenu: + case kWritingDirectionMenu: return true; - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + case kWritingDirectionDefault: + case kWritingDirectionLtr: + case kWritingDirectionRtl: return delegate_->IsTextDirectionEnabled( GetTextDirectionFromCommandId(command_id)); - case IDS_SPEECH_START_SPEAKING_MAC: + case kSpeechStartSpeaking: return true; - case IDS_SPEECH_STOP_SPEAKING_MAC: + case kSpeechStopSpeaking: return IsSpeaking(); } @@ -154,15 +167,15 @@ void TextServicesContextMenu::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_DEFAULT: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_LTR: - case IDS_CONTENT_CONTEXT_WRITING_DIRECTION_RTL: + case kWritingDirectionDefault: + case kWritingDirectionLtr: + case kWritingDirectionRtl: delegate_->UpdateTextDirection(GetTextDirectionFromCommandId(command_id)); break; - case IDS_SPEECH_START_SPEAKING_MAC: + case kSpeechStartSpeaking: SpeakText(delegate_->GetSelectedText()); break; - case IDS_SPEECH_STOP_SPEAKING_MAC: + case kSpeechStopSpeaking: StopSpeaking(); break; default: @@ -170,4 +183,4 @@ } } -} // namespace ui \ No newline at end of file +} // namespace ui
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc index 2a8cde4..22f43ff7 100644 --- a/ui/base/ime/win/tsf_text_store.cc +++ b/ui/base/ime/win/tsf_text_store.cc
@@ -1415,28 +1415,29 @@ // any style or not. span->thickness = attribute.fBoldLine ? ImeTextSpan::Thickness::kThick : ImeTextSpan::Thickness::kThin; - span->underline_style = ImeTextSpan::UnderlineStyle::kSolid; - if (attribute.lsStyle != TF_LS_NONE) { - switch (attribute.lsStyle) { - case TF_LS_SOLID: { - span->underline_style = ImeTextSpan::UnderlineStyle::kSolid; - break; - } - case TF_LS_DOT: { - span->underline_style = ImeTextSpan::UnderlineStyle::kDot; - break; - } - case TF_LS_DASH: { - span->underline_style = ImeTextSpan::UnderlineStyle::kDash; - break; - } - case TF_LS_SQUIGGLE: { - span->underline_style = ImeTextSpan::UnderlineStyle::kSquiggle; - break; - } - default: { - span->underline_style = ImeTextSpan::UnderlineStyle::kSolid; - } + switch (attribute.lsStyle) { + case TF_LS_SOLID: { + span->underline_style = ImeTextSpan::UnderlineStyle::kSolid; + break; + } + case TF_LS_DOT: { + span->underline_style = ImeTextSpan::UnderlineStyle::kDot; + break; + } + case TF_LS_DASH: { + span->underline_style = ImeTextSpan::UnderlineStyle::kDash; + break; + } + case TF_LS_SQUIGGLE: { + span->underline_style = ImeTextSpan::UnderlineStyle::kSquiggle; + break; + } + case TF_LS_NONE: { + span->underline_style = ImeTextSpan::UnderlineStyle::kNone; + break; + } + default: { + span->underline_style = ImeTextSpan::UnderlineStyle::kSolid; } } if (attribute.crText.type != TF_CT_NONE) {
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc index 6a55c0f..d5d058f 100644 --- a/ui/base/models/simple_menu_model.cc +++ b/ui/base/models/simple_menu_model.cc
@@ -80,6 +80,16 @@ } void SimpleMenuModel::AddItemWithStringId(int command_id, int string_id) { + // Prevent this dangerous pattern: + // model->AddItemWithStringId(IDS_FOO, IDS_FOO); + // This conflates string IDs with command IDs, which are separate namespaces. + // Sometimes this is an accident where this is meant: + // model->AddItemWithStringId(IDC_FOO, IDS_FOO); + // but sometimes it is deliberate, usually in situations where there is no + // matching IDC constant or the matching IDC constant is not available. + // Using IDS constants for command IDs can cause confusion elsewhere, since + // command IDs are usually either IDC values or strictly local constants. + DCHECK_NE(command_id, string_id); AddItem(command_id, l10n_util::GetStringUTF16(string_id)); }
diff --git a/ui/base/pointer/touch_editing_controller.h b/ui/base/pointer/touch_editing_controller.h index e735129b..e55fb3c9 100644 --- a/ui/base/pointer/touch_editing_controller.h +++ b/ui/base/pointer/touch_editing_controller.h
@@ -19,6 +19,15 @@ // using touch. class UI_BASE_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { public: + // Commands that all TouchEditables support: + enum MenuCommands { + // Don't use command ID 0 - a lot of tests use 0 for "no command". + kCut = 1, + kCopy, + kPaste, + kLastTouchEditableCommandId = kPaste, + }; + // TODO(mohsen): Consider switching from local coordinates to screen // coordinates in this interface and see if it will simplify things.
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn index 76584b2..5d4060d 100644 --- a/ui/base/x/BUILD.gn +++ b/ui/base/x/BUILD.gn
@@ -80,3 +80,18 @@ "//ui/platform_window/common", ] } + +source_set("gl") { + sources = [ + "x11_gl_egl_utility.cc", + "x11_gl_egl_utility.h", + ] + + configs += [ "//third_party/khronos:khronos_headers" ] + deps = [ + ":x", + "//base", + "//third_party/angle:includes", + "//ui/gl", + ] +}
diff --git a/ui/base/x/DEPS b/ui/base/x/DEPS index edeb0030..4a0553f 100644 --- a/ui/base/x/DEPS +++ b/ui/base/x/DEPS
@@ -1,3 +1,5 @@ include_rules = [ "+ui/platform_window/common/platform_window_defaults.h", + "+ui/gl/gl_surface_egl.h", + "+third_party/khronos/EGL/egl.h", ]
diff --git a/ui/base/x/x11_gl_egl_utility.cc b/ui/base/x/x11_gl_egl_utility.cc new file mode 100644 index 0000000..2a7fd03 --- /dev/null +++ b/ui/base/x/x11_gl_egl_utility.cc
@@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/x/x11_gl_egl_utility.h" + +#include "ui/base/x/x11_util_internal.h" +#include "ui/gfx/x/x11.h" +#include "ui/gl/gl_surface_egl.h" + +#ifndef EGL_ANGLE_x11_visual +#define EGL_ANGLE_x11_visual 1 +#define EGL_X11_VISUAL_ID_ANGLE 0x33A3 +#endif /* EGL_ANGLE_x11_visual */ + +#ifndef EGL_ANGLE_platform_angle_null +#define EGL_ANGLE_platform_angle_null 1 +#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE +#endif /* EGL_ANGLE_platform_angle_null */ + +namespace ui { + +void GetPlatformExtraDisplayAttribs(EGLenum platform_type, + std::vector<EGLAttrib>* attributes) { + // ANGLE_NULL doesn't use the visual, and may run without X11 where we can't + // get it anyway. + if (platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) { + Visual* visual; + ui::XVisualManager::GetInstance()->ChooseVisualForWindow( + true, &visual, nullptr, nullptr, nullptr); + attributes->push_back(EGL_X11_VISUAL_ID_ANGLE); + attributes->push_back(static_cast<EGLAttrib>(XVisualIDFromVisual(visual))); + } +} + +void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) { + // If we're using ANGLE_NULL, we may not have a display, in which case we + // can't use XVisualManager. + if (gl::GLSurfaceEGL::GetNativeDisplay() != EGL_DEFAULT_DISPLAY) { + ui::XVisualManager::GetInstance()->ChooseVisualForWindow( + true, nullptr, buffer_size, nullptr, nullptr); + *alpha_size = *buffer_size == 32 ? 8 : 0; + } +} + +} // namespace ui
diff --git a/ui/base/x/x11_gl_egl_utility.h b/ui/base/x/x11_gl_egl_utility.h new file mode 100644 index 0000000..eb3ca99a --- /dev/null +++ b/ui/base/x/x11_gl_egl_utility.h
@@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_X_X11_GL_EGL_UTILITY_H_ +#define UI_BASE_X_X11_GL_EGL_UTILITY_H_ + +#include <vector> + +#include "third_party/khronos/EGL/egl.h" + +namespace ui { + +// Returns display attributes for the given |platform_type|. +void GetPlatformExtraDisplayAttribs(EGLenum platform_type, + std::vector<EGLAttrib>* attributes); + +// Sets custom alpha and buffer size. +void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size); + +} // namespace ui + +#endif // UI_BASE_X_X11_GL_EGL_UTILITY_H_ \ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/toolbar_controller.js b/ui/file_manager/file_manager/foreground/js/toolbar_controller.js index 8181200..d797d8f8 100644 --- a/ui/file_manager/file_manager/foreground/js/toolbar_controller.js +++ b/ui/file_manager/file_manager/foreground/js/toolbar_controller.js
@@ -261,7 +261,6 @@ * @private */ onDeleteButtonClicked_() { - this.deleteButton_.blur(); this.deleteCommand_.canExecuteChange(this.listContainer_.currentList); this.deleteCommand_.execute(this.listContainer_.currentList); }
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 8fac30ee..2c9aba9 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -204,6 +204,8 @@ "gl_bindings_autogen_egl.h", "gl_context_egl.cc", "gl_context_egl.h", + "gl_display_egl_util.cc", + "gl_display_egl_util.h", "gl_egl_api_implementation.cc", "gl_egl_api_implementation.h", "gl_fence_egl.cc", @@ -255,6 +257,8 @@ if (use_x11) { sources += [ + "gl_surface_egl_x11.cc", + "gl_surface_egl_x11.h", "gl_surface_egl_x11_gles2.cc", "gl_surface_egl_x11_gles2.h", "gl_surface_glx_x11.cc",
diff --git a/ui/gl/gl_display_egl_util.cc b/ui/gl/gl_display_egl_util.cc new file mode 100644 index 0000000..923203a --- /dev/null +++ b/ui/gl/gl_display_egl_util.cc
@@ -0,0 +1,52 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_display_egl_util.h" + +#include "base/no_destructor.h" + +namespace gl { + +namespace { + +static GLDisplayEglUtil* g_instance = nullptr; + +class GLDisplayEglUtilStub : public GLDisplayEglUtil { + public: + static GLDisplayEglUtilStub* GetInstance() { + static base::NoDestructor<GLDisplayEglUtilStub> instance; + return instance.get(); + } + void GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) override {} + + void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) override {} + + private: + friend base::NoDestructor<GLDisplayEglUtilStub>; + + GLDisplayEglUtilStub() = default; + ~GLDisplayEglUtilStub() override = default; + GLDisplayEglUtilStub(const GLDisplayEglUtilStub& util) = delete; + GLDisplayEglUtilStub& operator=(const GLDisplayEglUtilStub& util) = delete; +}; + +} // namespace + +// static +GLDisplayEglUtil* GLDisplayEglUtil::GetInstance() { + // If a platform specific impl is not set, create a stub instance. + if (!g_instance) + SetInstance(GLDisplayEglUtilStub::GetInstance()); + return g_instance; +} + +// static +void GLDisplayEglUtil::SetInstance(GLDisplayEglUtil* gl_display_util) { + g_instance = gl_display_util; +} + +} // namespace gl
diff --git a/ui/gl/gl_display_egl_util.h b/ui/gl/gl_display_egl_util.h new file mode 100644 index 0000000..1566704 --- /dev/null +++ b/ui/gl/gl_display_egl_util.h
@@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_DISPLAY_EGL_UTIL_H_ +#define UI_GL_GL_DISPLAY_EGL_UTIL_H_ + +#include <vector> + +#include "third_party/khronos/EGL/egl.h" +#include "ui/gl/gl_export.h" +#include "ui/gl/gl_surface_egl.h" + +namespace gl { + +// Utility singleton class that helps to set additional egl properties. This +// class should be implemented by each platform except Ozone. In case of Ozone, +// there is a common implementation that forwards calls to a public interface of +// a platform. +// The reason why it is defined here in ui/gl is that ui/gl cannot depend on +// ozone and we have to provide an interface here. ui/gl/init will provide an +// implementation for this utility class upon initialization of gl. +class GL_EXPORT GLDisplayEglUtil { + public: + // Returns either set instance or stub instance. + static GLDisplayEglUtil* GetInstance(); + + static void SetInstance(GLDisplayEglUtil* gl_display_util); + + // Returns display attributes for the given |platform_type|. Each platform can + // have different attributes. + virtual void GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) = 0; + + // Sets custom alpha and buffer size for a given platform. By default, the + // values are not modified. + virtual void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) = 0; + + protected: + virtual ~GLDisplayEglUtil() = default; +}; + +} // namespace gl + +#endif // UI_GL_GL_DISPLAY_EGL_UTIL_H_
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 750f3ede2..5e4f30b8 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc
@@ -20,7 +20,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/system/sys_info.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "ui/events/platform/platform_event_dispatcher.h" @@ -30,6 +29,7 @@ #include "ui/gl/egl_util.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_context_egl.h" +#include "ui/gl/gl_display_egl_util.h" #include "ui/gl/gl_image.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface_presentation_helper.h" @@ -204,37 +204,6 @@ static base::LazyInstance<TraceSwapEventsInitializer>::Leaky g_trace_swap_enabled = LAZY_INSTANCE_INITIALIZER; -#if defined(USE_X11) -class XrandrIntervalOnlyVSyncProvider : public gfx::VSyncProvider { - public: - XrandrIntervalOnlyVSyncProvider(Display* display) - : display_(display), interval_(base::TimeDelta::FromSeconds(1 / 60.)) {} - - void GetVSyncParameters(UpdateVSyncCallback callback) override { - if (++calls_since_last_update_ >= kCallsBetweenUpdates) { - calls_since_last_update_ = 0; - interval_ = ui::GetPrimaryDisplayRefreshIntervalFromXrandr(display_); - } - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), base::TimeTicks(), interval_)); - } - - bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase, - base::TimeDelta* interval) override { - return false; - } - bool SupportGetVSyncParametersIfAvailable() const override { return false; } - bool IsHWClock() const override { return false; } - - private: - Display* const display_ = nullptr; - base::TimeDelta interval_; - static const int kCallsBetweenUpdates = 100; - int calls_since_last_update_ = kCallsBetweenUpdates; -}; -#endif - class EGLSyncControlVSyncProvider : public SyncControlVSyncProvider { public: explicit EGLSyncControlVSyncProvider(EGLSurface surface) @@ -313,18 +282,8 @@ display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); display_attribs.push_back(static_cast<EGLAttrib>(platform_type)); -#if defined(USE_X11) - // ANGLE_NULL doesn't use the visual, and may run without X11 where we can't - // get it anyway. - if (platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) { - Visual* visual; - ui::XVisualManager::GetInstance()->ChooseVisualForWindow( - true, &visual, nullptr, nullptr, nullptr); - display_attribs.push_back(EGL_X11_VISUAL_ID_ANGLE); - display_attribs.push_back( - static_cast<EGLAttrib>(XVisualIDFromVisual(visual))); - } -#endif + GLDisplayEglUtil::GetInstance()->GetPlatformExtraDisplayAttribs( + platform_type, &display_attribs); std::vector<const char*> enabled_features_attribs = GetAttribArrayFromStringVector(enabled_features); @@ -574,15 +533,10 @@ EGLint stencil_size = format.GetStencilBits(); EGLint samples = format.GetSamples(); -#if defined(USE_X11) - // If we're using ANGLE_NULL, we may not have a display, in which case we - // can't use XVisualManager. - if (g_native_display.GetDisplay() != EGL_DEFAULT_DISPLAY) { - ui::XVisualManager::GetInstance()->ChooseVisualForWindow( - true, nullptr, &buffer_size, nullptr, nullptr); - alpha_size = buffer_size == 32 ? 8 : 0; - } -#endif + // Some platforms (eg. X11) may want to set custom values for alpha and buffer + // sizes. + GLDisplayEglUtil::GetInstance()->ChoosePlatformCustomAlphaAndBufferSize( + &alpha_size, &buffer_size); EGLint surface_type = (surfaceless ? EGL_DONT_CARE : EGL_WINDOW_BIT | EGL_PBUFFER_BIT); @@ -1372,34 +1326,8 @@ std::make_unique<EGLSyncControlVSyncProvider>(surface_); } -#if defined(USE_X11) - // Query all child windows and store them. ANGLE creates a child window when - // eglCreateWidnowSurface is called on X11 and expose events from this window - // need to be received by this class. - Display* x11_display = GetNativeDisplay(); - Window root = 0; - Window parent = 0; - Window* children = nullptr; - unsigned num_children = 0; - if (XQueryTree(x11_display, window_, &root, &parent, &children, - &num_children)) { - for (unsigned int i = 0; i < num_children; ++i) { - children_.push_back(children[i]); - } - if (num_children > 0) { - XFree(children); - } - } - - if (ui::X11EventSource::HasInstance()) { - ui::X11EventSource::GetInstance()->AddXEventDispatcher(this); - } - - if (!vsync_provider_external_ && !vsync_provider_internal_) { - vsync_provider_internal_ = - std::make_unique<XrandrIntervalOnlyVSyncProvider>(x11_display); - } -#endif + if (!vsync_provider_external_ && !vsync_provider_internal_) + vsync_provider_internal_ = CreateVsyncProviderInternal(); presentation_helper_ = std::make_unique<GLSurfacePresentationHelper>(GetVSyncProvider()); @@ -1496,11 +1424,6 @@ vsync_provider_internal_ = nullptr; if (surface_) { -#if defined(USE_X11) - if (ui::X11EventSource::HasInstance()) { - ui::X11EventSource::GetInstance()->RemoveXEventDispatcher(this); - } -#endif if (!eglDestroySurface(GetDisplay(), surface_)) { LOG(ERROR) << "eglDestroySurface failed with error " << GetLastEGLErrorString(); @@ -1544,17 +1467,6 @@ UpdateSwapEvents(new_frame_id, new_frame_id_is_valid); } -#if defined(USE_X11) - // We need to restore the background pixel that we set to WhitePixel on - // views::DesktopWindowTreeHostX11::InitX11Window back to None for the - // XWindow associated to this surface after the first SwapBuffers has - // happened, to avoid showing a weird white background while resizing. - if (GetNativeDisplay() && !has_swapped_buffers_) { - XSetWindowBackgroundPixmap(GetNativeDisplay(), window_, 0); - has_swapped_buffers_ = true; - } -#endif - return scoped_swap_buffers.result(); } @@ -1673,6 +1585,11 @@ } } +std::unique_ptr<gfx::VSyncProvider> +NativeViewGLSurfaceEGL::CreateVsyncProviderInternal() { + return nullptr; +} + gfx::Size NativeViewGLSurfaceEGL::GetSize() { EGLint width; EGLint height; @@ -1981,25 +1898,6 @@ return success; } -#if defined(USE_X11) -bool NativeViewGLSurfaceEGL::DispatchXEvent(XEvent* x_event) { - // When ANGLE is used for EGL, it creates an X11 child window. Expose events - // from this window need to be forwarded to this class. - bool can_dispatch = x_event->type == Expose && - std::find(children_.begin(), children_.end(), - x_event->xexpose.window) != children_.end(); - - if (!can_dispatch) - return false; - - x_event->xexpose.window = window_; - Display* x11_display = GetNativeDisplay(); - XSendEvent(x11_display, window_, x11::False, ExposureMask, x_event); - XFlush(x11_display); - return true; -} -#endif - PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size) : size_(size), surface_(NULL) {
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h index 10099277..191d055 100644 --- a/ui/gl/gl_surface_egl.h +++ b/ui/gl/gl_surface_egl.h
@@ -27,10 +27,6 @@ #include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface_overlay.h" -#if defined(USE_X11) -#include "ui/events/platform/x11/x11_event_source.h" // nogncheck -#endif - namespace gl { class EGLDisplayPlatform { @@ -136,9 +132,6 @@ // Encapsulates an EGL surface bound to a view. class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL, -#if defined(USE_X11) - public ui::XEventDispatcher, -#endif public EGLTimestampClient { public: NativeViewGLSurfaceEGL(EGLNativeWindowType window, @@ -194,7 +187,6 @@ ~NativeViewGLSurfaceEGL() override; EGLNativeWindowType window_ = 0; - std::vector<EGLNativeWindowType> children_; gfx::Size size_ = gfx::Size(1, 1); bool enable_fixed_size_angle_ = true; @@ -213,20 +205,14 @@ void UpdateSwapEvents(EGLuint64KHR newFrameId, bool newFrameIdIsValid); void TraceSwapEvents(EGLuint64KHR oldFrameId); -#if defined(USE_X11) - // XEventDispatcher: - bool DispatchXEvent(XEvent* xev) override; -#endif + // Some platforms may provide a custom implementation of vsync provider. + virtual std::unique_ptr<gfx::VSyncProvider> CreateVsyncProviderInternal(); EGLSurface surface_ = nullptr; bool supports_post_sub_buffer_ = false; bool supports_swap_buffer_with_damage_ = false; gfx::SurfaceOrigin surface_origin_ = gfx::SurfaceOrigin::kBottomLeft; -#if defined(USE_X11) - bool has_swapped_buffers_ = false; -#endif - std::unique_ptr<gfx::VSyncProvider> vsync_provider_external_; std::unique_ptr<gfx::VSyncProvider> vsync_provider_internal_;
diff --git a/ui/gl/gl_surface_egl_x11.cc b/ui/gl/gl_surface_egl_x11.cc new file mode 100644 index 0000000..fbb53bf --- /dev/null +++ b/ui/gl/gl_surface_egl_x11.cc
@@ -0,0 +1,128 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_surface_egl_x11.h" + +#include "base/threading/thread_task_runner_handle.h" +#include "ui/base/x/x11_display_util.h" +#include "ui/gfx/x/x11.h" +#include "ui/gl/egl_util.h" + +namespace gl { + +namespace { + +class XrandrIntervalOnlyVSyncProvider : public gfx::VSyncProvider { + public: + explicit XrandrIntervalOnlyVSyncProvider(Display* display) + : display_(display), interval_(base::TimeDelta::FromSeconds(1 / 60.)) {} + + void GetVSyncParameters(UpdateVSyncCallback callback) override { + if (++calls_since_last_update_ >= kCallsBetweenUpdates) { + calls_since_last_update_ = 0; + interval_ = ui::GetPrimaryDisplayRefreshIntervalFromXrandr(display_); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), base::TimeTicks(), interval_)); + } + + bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase, + base::TimeDelta* interval) override { + return false; + } + bool SupportGetVSyncParametersIfAvailable() const override { return false; } + bool IsHWClock() const override { return false; } + + private: + Display* const display_ = nullptr; + base::TimeDelta interval_; + static const int kCallsBetweenUpdates = 100; + int calls_since_last_update_ = kCallsBetweenUpdates; +}; + +} // namespace + +NativeViewGLSurfaceEGLX11::NativeViewGLSurfaceEGLX11(EGLNativeWindowType window) + : NativeViewGLSurfaceEGL(window, nullptr) {} + +bool NativeViewGLSurfaceEGLX11::Initialize(GLSurfaceFormat format) { + if (!NativeViewGLSurfaceEGL::Initialize(format)) + return false; + + // Query all child windows and store them. ANGLE creates a child window when + // eglCreateWidnowSurface is called on X11 and expose events from this window + // need to be received by this class. + Display* x11_display = GetNativeDisplay(); + Window root = 0; + Window parent = 0; + Window* children = nullptr; + unsigned num_children = 0; + if (XQueryTree(x11_display, window_, &root, &parent, &children, + &num_children)) { + for (unsigned int i = 0; i < num_children; ++i) { + children_.push_back(children[i]); + } + if (num_children > 0) { + XFree(children); + } + } + + if (ui::X11EventSource::HasInstance()) { + dispatcher_set_ = true; + ui::X11EventSource::GetInstance()->AddXEventDispatcher(this); + } + return true; +} + +void NativeViewGLSurfaceEGLX11::Destroy() { + NativeViewGLSurfaceEGL::Destroy(); + if (dispatcher_set_ && ui::X11EventSource::HasInstance()) + ui::X11EventSource::GetInstance()->RemoveXEventDispatcher(this); +} + +gfx::SwapResult NativeViewGLSurfaceEGLX11::SwapBuffers( + PresentationCallback callback) { + auto result = NativeViewGLSurfaceEGL::SwapBuffers(std::move(callback)); + if (result == gfx::SwapResult::SWAP_FAILED) + return result; + + // We need to restore the background pixel that we set to WhitePixel on + // views::DesktopWindowTreeHostX11::InitX11Window back to None for the + // XWindow associated to this surface after the first SwapBuffers has + // happened, to avoid showing a weird white background while resizing. + if (GetNativeDisplay() && !has_swapped_buffers_) { + XSetWindowBackgroundPixmap(GetNativeDisplay(), window_, 0); + has_swapped_buffers_ = true; + } + return result; +} + +NativeViewGLSurfaceEGLX11::~NativeViewGLSurfaceEGLX11() { + Destroy(); +} + +std::unique_ptr<gfx::VSyncProvider> +NativeViewGLSurfaceEGLX11::CreateVsyncProviderInternal() { + return std::make_unique<XrandrIntervalOnlyVSyncProvider>(GetNativeDisplay()); +} + +bool NativeViewGLSurfaceEGLX11::DispatchXEvent(XEvent* x_event) { + // When ANGLE is used for EGL, it creates an X11 child window. Expose events + // from this window need to be forwarded to this class. + bool can_dispatch = x_event->type == Expose && + std::find(children_.begin(), children_.end(), + x_event->xexpose.window) != children_.end(); + + if (!can_dispatch) + return false; + + x_event->xexpose.window = window_; + Display* x11_display = GetNativeDisplay(); + XSendEvent(x11_display, window_, x11::False, ExposureMask, x_event); + XFlush(x11_display); + return true; +} + +} // namespace gl
diff --git a/ui/gl/gl_surface_egl_x11.h b/ui/gl/gl_surface_egl_x11.h new file mode 100644 index 0000000..925b35c --- /dev/null +++ b/ui/gl/gl_surface_egl_x11.h
@@ -0,0 +1,53 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_SURFACE_EGL_X11_H_ +#define UI_GL_GL_SURFACE_EGL_X11_H_ + +#include <stdint.h> + +#include <string> + +#include "base/macros.h" +#include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gl/gl_export.h" +#include "ui/gl/gl_surface_egl.h" + +namespace gl { + +// Encapsulates an EGL surface bound to a view using the X Window System. +class GL_EXPORT NativeViewGLSurfaceEGLX11 : public NativeViewGLSurfaceEGL, + public ui::XEventDispatcher { + public: + explicit NativeViewGLSurfaceEGLX11(EGLNativeWindowType window); + NativeViewGLSurfaceEGLX11(const NativeViewGLSurfaceEGLX11& other) = delete; + NativeViewGLSurfaceEGLX11& operator=(const NativeViewGLSurfaceEGLX11& rhs) = + delete; + + // NativeViewGLSurfaceEGL overrides. + bool Initialize(GLSurfaceFormat format) override; + void Destroy() override; + gfx::SwapResult SwapBuffers(PresentationCallback callback) override; + + protected: + ~NativeViewGLSurfaceEGLX11() override; + + private: + // NativeViewGLSurfaceEGL overrides: + std::unique_ptr<gfx::VSyncProvider> CreateVsyncProviderInternal() override; + + // XEventDispatcher: + bool DispatchXEvent(XEvent* xev) override; + + std::vector<Window> children_; + + // Indicates if the dispatcher has been set. + bool dispatcher_set_ = false; + + bool has_swapped_buffers_ = false; +}; + +} // namespace gl + +#endif // UI_GL_GL_SURFACE_EGL_X11_H_
diff --git a/ui/gl/gl_surface_egl_x11_gles2.cc b/ui/gl/gl_surface_egl_x11_gles2.cc index 684eb63..c68a18f 100644 --- a/ui/gl/gl_surface_egl_x11_gles2.cc +++ b/ui/gl/gl_surface_egl_x11_gles2.cc
@@ -14,7 +14,7 @@ NativeViewGLSurfaceEGLX11GLES2::NativeViewGLSurfaceEGLX11GLES2( EGLNativeWindowType window) - : NativeViewGLSurfaceEGL(0, nullptr), parent_window_(window) {} + : NativeViewGLSurfaceEGLX11(0), parent_window_(window) {} bool NativeViewGLSurfaceEGLX11GLES2::InitializeNativeWindow() { Display* x11_display = GetNativeDisplay(); @@ -46,7 +46,7 @@ } void NativeViewGLSurfaceEGLX11GLES2::Destroy() { - NativeViewGLSurfaceEGL::Destroy(); + NativeViewGLSurfaceEGLX11::Destroy(); if (window_) { Display* x11_display = GetNativeDisplay();
diff --git a/ui/gl/gl_surface_egl_x11_gles2.h b/ui/gl/gl_surface_egl_x11_gles2.h index fcf17dc..7039b34d 100644 --- a/ui/gl/gl_surface_egl_x11_gles2.h +++ b/ui/gl/gl_surface_egl_x11_gles2.h
@@ -11,12 +11,13 @@ #include "base/macros.h" #include "ui/gl/gl_export.h" -#include "ui/gl/gl_surface_egl.h" +#include "ui/gl/gl_surface_egl_x11.h" namespace gl { // Encapsulates an EGL surface bound to a view using the X Window System. -class GL_EXPORT NativeViewGLSurfaceEGLX11GLES2 : public NativeViewGLSurfaceEGL { +class GL_EXPORT NativeViewGLSurfaceEGLX11GLES2 + : public NativeViewGLSurfaceEGLX11 { public: explicit NativeViewGLSurfaceEGLX11GLES2(EGLNativeWindowType window);
diff --git a/ui/gl/init/BUILD.gn b/ui/gl/init/BUILD.gn index 921e567..f2708299 100644 --- a/ui/gl/init/BUILD.gn +++ b/ui/gl/init/BUILD.gn
@@ -58,13 +58,23 @@ libs = [ "OpenGL.framework" ] } else if (use_x11) { sources += [ + "gl_display_egl_util_x11.cc", + "gl_display_egl_util_x11.h", "gl_factory_x11.cc", "gl_initializer_x11.cc", ] - deps += [ "//ui/gfx/x" ] + configs += [ "//build/config/linux:x11" ] + + deps += [ + "//ui/base/x", + "//ui/base/x:gl", + "//ui/gfx/x", + ] } else if (use_ozone) { sources += [ + "gl_display_egl_util_ozone.cc", + "gl_display_egl_util_ozone.h", "gl_factory_ozone.cc", "gl_initializer_ozone.cc", "ozone_util.h",
diff --git a/ui/gl/init/gl_display_egl_util_ozone.cc b/ui/gl/init/gl_display_egl_util_ozone.cc new file mode 100644 index 0000000..fd00349 --- /dev/null +++ b/ui/gl/init/gl_display_egl_util_ozone.cc
@@ -0,0 +1,38 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/init/gl_display_egl_util_ozone.h" + +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/platform_gl_egl_utility.h" + +namespace gl { + +// static +GLDisplayEglUtilOzone* GLDisplayEglUtilOzone::GetInstance() { + static base::NoDestructor<GLDisplayEglUtilOzone> instance; + return instance.get(); +} + +void GLDisplayEglUtilOzone::GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) { + auto* utility = ui::OzonePlatform::GetInstance()->GetPlatformGLEGLUtility(); + if (utility) + utility->GetAdditionalEGLAttributes(platform_type, attributes); +} + +void GLDisplayEglUtilOzone::ChoosePlatformCustomAlphaAndBufferSize( + EGLint* alpha_size, + EGLint* buffer_size) { + auto* utility = ui::OzonePlatform::GetInstance()->GetPlatformGLEGLUtility(); + if (utility) + utility->ChooseEGLAlphaAndBufferSize(alpha_size, buffer_size); +} + +GLDisplayEglUtilOzone::GLDisplayEglUtilOzone() = default; + +GLDisplayEglUtilOzone::~GLDisplayEglUtilOzone() = default; + +} // namespace gl
diff --git a/ui/gl/init/gl_display_egl_util_ozone.h b/ui/gl/init/gl_display_egl_util_ozone.h new file mode 100644 index 0000000..32ecce6 --- /dev/null +++ b/ui/gl/init/gl_display_egl_util_ozone.h
@@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_INIT_GL_DISPLAY_EGL_UTIL_OZONE_H_ +#define UI_GL_INIT_GL_DISPLAY_EGL_UTIL_OZONE_H_ + +#include <vector> + +#include "base/no_destructor.h" +#include "ui/gl/gl_display_egl_util.h" + +namespace gl { + +// Forwards calls to PlatformGLEGLUtility. It might be implemented by some +// platforms. +class GLDisplayEglUtilOzone : public GLDisplayEglUtil { + public: + static GLDisplayEglUtilOzone* GetInstance(); + + // GLDisplayEglUtil overrides: + void GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) override; + void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) override; + + private: + friend base::NoDestructor<GLDisplayEglUtilOzone>; + + GLDisplayEglUtilOzone(); + ~GLDisplayEglUtilOzone() override; + GLDisplayEglUtilOzone(const GLDisplayEglUtilOzone& util) = delete; + GLDisplayEglUtilOzone& operator=(const GLDisplayEglUtilOzone& util) = delete; +}; + +} // namespace gl + +#endif // UI_GL_INIT_GL_DISPLAY_EGL_UTIL_OZONE_H_
diff --git a/ui/gl/init/gl_display_egl_util_x11.cc b/ui/gl/init/gl_display_egl_util_x11.cc new file mode 100644 index 0000000..182291b8 --- /dev/null +++ b/ui/gl/init/gl_display_egl_util_x11.cc
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/init/gl_display_egl_util_x11.h" + +#include "ui/base/x/x11_gl_egl_utility.h" + +namespace gl { + +// static +GLDisplayEglUtilX11* GLDisplayEglUtilX11::GetInstance() { + static base::NoDestructor<GLDisplayEglUtilX11> instance; + return instance.get(); +} + +void GLDisplayEglUtilX11::GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) { + ui::GetPlatformExtraDisplayAttribs(platform_type, attributes); +} + +void GLDisplayEglUtilX11::ChoosePlatformCustomAlphaAndBufferSize( + EGLint* alpha_size, + EGLint* buffer_size) { + ui::ChoosePlatformCustomAlphaAndBufferSize(alpha_size, buffer_size); +} + +GLDisplayEglUtilX11::GLDisplayEglUtilX11() = default; + +GLDisplayEglUtilX11::~GLDisplayEglUtilX11() = default; + +} // namespace gl \ No newline at end of file
diff --git a/ui/gl/init/gl_display_egl_util_x11.h b/ui/gl/init/gl_display_egl_util_x11.h new file mode 100644 index 0000000..290de7f --- /dev/null +++ b/ui/gl/init/gl_display_egl_util_x11.h
@@ -0,0 +1,36 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_INIT_GL_DISPLAY_EGL_UTIL_X11_H_ +#define UI_GL_INIT_GL_DISPLAY_EGL_UTIL_X11_H_ + +#include <vector> + +#include "base/no_destructor.h" +#include "ui/gl/gl_display_egl_util.h" + +namespace gl { + +class GLDisplayEglUtilX11 : public GLDisplayEglUtil { + public: + static GLDisplayEglUtilX11* GetInstance(); + + // GLDisplayEglUtil overrides: + void GetPlatformExtraDisplayAttribs( + EGLenum platform_type, + std::vector<EGLAttrib>* attributes) override; + void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) override; + + private: + friend base::NoDestructor<GLDisplayEglUtilX11>; + GLDisplayEglUtilX11(); + ~GLDisplayEglUtilX11() override; + GLDisplayEglUtilX11(const GLDisplayEglUtilX11& util) = delete; + GLDisplayEglUtilX11& operator=(const GLDisplayEglUtilX11& util) = delete; +}; + +} // namespace gl + +#endif // UI_GL_INIT_GL_DISPLAY_EGL_UTIL_X11_H_
diff --git a/ui/gl/init/gl_factory_x11.cc b/ui/gl/init/gl_factory_x11.cc index 75c9f0e..4bebef1 100644 --- a/ui/gl/init/gl_factory_x11.cc +++ b/ui/gl/init/gl_factory_x11.cc
@@ -14,7 +14,7 @@ #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" -#include "ui/gl/gl_surface_egl.h" +#include "ui/gl/gl_surface_egl_x11.h" #include "ui/gl/gl_surface_egl_x11_gles2.h" #include "ui/gl/gl_surface_glx.h" #include "ui/gl/gl_surface_glx_x11.h" @@ -83,7 +83,7 @@ return InitializeGLSurface(new NativeViewGLSurfaceEGLX11GLES2(window)); case kGLImplementationEGLANGLE: DCHECK(window != gfx::kNullAcceleratedWidget); - return InitializeGLSurface(new NativeViewGLSurfaceEGL(window, nullptr)); + return InitializeGLSurface(new NativeViewGLSurfaceEGLX11(window)); case kGLImplementationMockGL: case kGLImplementationStubGL: return new GLSurfaceStub;
diff --git a/ui/gl/init/gl_initializer_ozone.cc b/ui/gl/init/gl_initializer_ozone.cc index 754b36c..4dfcebd 100644 --- a/ui/gl/init/gl_initializer_ozone.cc +++ b/ui/gl/init/gl_initializer_ozone.cc
@@ -8,14 +8,18 @@ #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_gl_api_implementation.h" #include "ui/gl/gl_surface.h" +#include "ui/gl/init/gl_display_egl_util_ozone.h" #include "ui/gl/init/ozone_util.h" +#include "ui/ozone/public/ozone_platform.h" namespace gl { namespace init { bool InitializeGLOneOffPlatform() { - if (HasGLOzone()) + if (HasGLOzone()) { + gl::GLDisplayEglUtil::SetInstance(gl::GLDisplayEglUtilOzone::GetInstance()); return GetGLOzone()->InitializeGLOneOffPlatform(); + } switch (GetGLImplementation()) { case kGLImplementationMockGL:
diff --git a/ui/gl/init/gl_initializer_x11.cc b/ui/gl/init/gl_initializer_x11.cc index d9190a95..d76d146 100644 --- a/ui/gl/init/gl_initializer_x11.cc +++ b/ui/gl/init/gl_initializer_x11.cc
@@ -20,6 +20,7 @@ #include "ui/gl/gl_surface_egl.h" #include "ui/gl/gl_surface_glx.h" #include "ui/gl/gl_switches.h" +#include "ui/gl/init/gl_display_egl_util_x11.h" namespace gl { namespace init { @@ -152,6 +153,8 @@ case kGLImplementationSwiftShaderGL: case kGLImplementationEGLGLES2: case kGLImplementationEGLANGLE: + // Set utility class that helps to initialize egl platform. + gl::GLDisplayEglUtil::SetInstance(gl::GLDisplayEglUtilX11::GetInstance()); if (!GLSurfaceEGL::InitializeOneOff( EGLDisplayPlatform(gfx::GetXDisplay()))) { LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn index 7e53cb2a..3e2260f 100644 --- a/ui/ozone/BUILD.gn +++ b/ui/ozone/BUILD.gn
@@ -85,6 +85,7 @@ "public/ozone_switches.cc", "public/ozone_switches.h", "public/platform_clipboard.h", + "public/platform_gl_egl_utility.h", "public/platform_screen.cc", "public/platform_screen.h", "public/platform_window_surface.h", @@ -136,6 +137,8 @@ "//ui/base/ime/chromeos/*", ] + configs += [ "//third_party/khronos:khronos_headers" ] + # Out of tree platforms can depend on this. visibility += ozone_external_platform_visibility }
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn index f1941921..10b7bdb 100644 --- a/ui/ozone/platform/x11/BUILD.gn +++ b/ui/ozone/platform/x11/BUILD.gn
@@ -12,6 +12,8 @@ sources = [ "client_native_pixmap_factory_x11.cc", "client_native_pixmap_factory_x11.h", + "gl_egl_utility_x11.cc", + "gl_egl_utility_x11.h", "gl_ozone_glx.cc", "gl_ozone_glx.h", "gl_surface_egl_ozone_x11.cc", @@ -50,6 +52,7 @@ "//ui/base/clipboard:clipboard_types", "//ui/base/ime", "//ui/base/x", + "//ui/base/x:gl", "//ui/display/fake", "//ui/events", "//ui/events/devices",
diff --git a/ui/ozone/platform/x11/gl_egl_utility_x11.cc b/ui/ozone/platform/x11/gl_egl_utility_x11.cc new file mode 100644 index 0000000..5b6673be5 --- /dev/null +++ b/ui/ozone/platform/x11/gl_egl_utility_x11.cc
@@ -0,0 +1,25 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/x11/gl_egl_utility_x11.h" + +#include "ui/base/x/x11_gl_egl_utility.h" + +namespace ui { + +GLEGLUtilityX11::GLEGLUtilityX11() = default; +GLEGLUtilityX11::~GLEGLUtilityX11() = default; + +void GLEGLUtilityX11::GetAdditionalEGLAttributes( + EGLenum platform_type, + std::vector<EGLAttrib>* display_attributes) { + GetPlatformExtraDisplayAttribs(platform_type, display_attributes); +} + +void GLEGLUtilityX11::ChooseEGLAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) { + ChoosePlatformCustomAlphaAndBufferSize(alpha_size, buffer_size); +} + +} // namespace ui
diff --git a/ui/ozone/platform/x11/gl_egl_utility_x11.h b/ui/ozone/platform/x11/gl_egl_utility_x11.h new file mode 100644 index 0000000..e9a9981b --- /dev/null +++ b/ui/ozone/platform/x11/gl_egl_utility_x11.h
@@ -0,0 +1,30 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_X11_GL_EGL_UTILITY_X11_H_ +#define UI_OZONE_PLATFORM_X11_GL_EGL_UTILITY_X11_H_ + +#include "ui/ozone/public/platform_gl_egl_utility.h" + +namespace ui { + +// Allows EGL to ask platforms for platform specific EGL attributes. +class GLEGLUtilityX11 : public PlatformGLEGLUtility { + public: + GLEGLUtilityX11(); + ~GLEGLUtilityX11() override; + GLEGLUtilityX11(const GLEGLUtilityX11& util) = delete; + GLEGLUtilityX11& operator=(const GLEGLUtilityX11& util) = delete; + + // PlatformGLEGLUtility overrides: + void GetAdditionalEGLAttributes( + EGLenum platform_type, + std::vector<EGLAttrib>* display_attributes) override; + void ChooseEGLAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) override; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_X11_GL_EGL_UTILITY_X11_H_
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc index 78ea2a9..a53c88d 100644 --- a/ui/ozone/platform/x11/ozone_platform_x11.cc +++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -21,6 +21,7 @@ #include "ui/gfx/x/x11_connection.h" #include "ui/gfx/x/x11_types.h" #include "ui/ozone/common/stub_overlay_manager.h" +#include "ui/ozone/platform/x11/gl_egl_utility_x11.h" #include "ui/ozone/platform/x11/x11_clipboard_ozone.h" #include "ui/ozone/platform/x11/x11_cursor_factory_ozone.h" #include "ui/ozone/platform/x11/x11_screen_ozone.h" @@ -122,6 +123,10 @@ return clipboard_.get(); } + PlatformGLEGLUtility* GetPlatformGLEGLUtility() override { + return gl_egl_utility_.get(); + } + std::unique_ptr<InputMethod> CreateInputMethod( internal::InputMethodDelegate* delegate, gfx::AcceleratedWidget) override { @@ -180,6 +185,7 @@ CreatePlatformEventSource(); surface_factory_ozone_ = std::make_unique<X11SurfaceFactory>(); + gl_egl_utility_ = std::make_unique<GLEGLUtilityX11>(); } private: @@ -228,6 +234,7 @@ // Objects in the GPU process. std::unique_ptr<X11SurfaceFactory> surface_factory_ozone_; + std::unique_ptr<GLEGLUtilityX11> gl_egl_utility_; // Objects in both UI and GPU process. std::unique_ptr<X11EventSource> event_source_;
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc index 35bae77..c160e43e 100644 --- a/ui/ozone/public/ozone_platform.cc +++ b/ui/ozone/public/ozone_platform.cc
@@ -87,6 +87,10 @@ return nullptr; } +PlatformGLEGLUtility* OzonePlatform::GetPlatformGLEGLUtility() { + return nullptr; +} + bool OzonePlatform::IsNativePixmapConfigSupported( gfx::BufferFormat format, gfx::BufferUsage usage) const {
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index c1d82b8b..2d9b665 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h
@@ -36,6 +36,7 @@ class SurfaceFactoryOzone; class SystemInputInjector; class PlatformClipboard; +class PlatformGLEGLUtility; namespace internal { class InputMethodDelegate; @@ -152,6 +153,7 @@ virtual std::unique_ptr<InputMethod> CreateInputMethod( internal::InputMethodDelegate* delegate, gfx::AcceleratedWidget widget) = 0; + virtual PlatformGLEGLUtility* GetPlatformGLEGLUtility(); // Returns true if the specified buffer format is supported. virtual bool IsNativePixmapConfigSupported(gfx::BufferFormat format,
diff --git a/ui/ozone/public/platform_gl_egl_utility.h b/ui/ozone/public/platform_gl_egl_utility.h new file mode 100644 index 0000000..704dc178 --- /dev/null +++ b/ui/ozone/public/platform_gl_egl_utility.h
@@ -0,0 +1,34 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PUBLIC_PLATFORM_GL_EGL_UTILITY_H_ +#define UI_OZONE_PUBLIC_PLATFORM_GL_EGL_UTILITY_H_ + +#include <string> +#include <unordered_map> +#include <vector> + +#include "base/component_export.h" +#include "third_party/khronos/EGL/egl.h" + +namespace ui { + +// Provides platform specific EGL attributes/configs. +class COMPONENT_EXPORT(OZONE_BASE) PlatformGLEGLUtility { + public: + virtual ~PlatformGLEGLUtility() = default; + + // Gets additional display attributes based on |platform_type|. + virtual void GetAdditionalEGLAttributes( + EGLenum platform_type, + std::vector<EGLAttrib>* display_attributes) = 0; + + // Chooses alpha and buffer size values. + virtual void ChooseEGLAlphaAndBufferSize(EGLint* alpha_size, + EGLint* buffer_size) = 0; +}; + +} // namespace ui + +#endif // UI_OZONE_PUBLIC_PLATFORM_GL_EGL_UTILITY_H_
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index c15c27a..f389c326 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -895,9 +895,9 @@ bool Label::IsCommandIdEnabled(int command_id) const { switch (command_id) { - case IDS_APP_COPY: + case MenuCommands::kCopy: return HasSelection() && !GetObscured(); - case IDS_APP_SELECT_ALL: + case MenuCommands::kSelectAll: return GetRenderTextForSelectionController() && !GetText().empty(); } return false; @@ -905,10 +905,10 @@ void Label::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { - case IDS_APP_COPY: + case MenuCommands::kCopy: CopyToClipboard(); break; - case IDS_APP_SELECT_ALL: + case MenuCommands::kSelectAll: SelectAll(); DCHECK(HasSelection()); UpdateSelectionClipboard(); @@ -921,11 +921,11 @@ bool Label::GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) const { switch (command_id) { - case IDS_APP_COPY: + case MenuCommands::kCopy: *accelerator = ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN); return true; - case IDS_APP_SELECT_ALL: + case MenuCommands::kSelectAll: *accelerator = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN); return true; @@ -1101,8 +1101,8 @@ } void Label::BuildContextMenuContents() { - context_menu_contents_.AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); - context_menu_contents_.AddItemWithStringId(IDS_APP_SELECT_ALL, + context_menu_contents_.AddItemWithStringId(MenuCommands::kCopy, IDS_APP_COPY); + context_menu_contents_.AddItemWithStringId(MenuCommands::kSelectAll, IDS_APP_SELECT_ALL); }
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h index 4cb533c..a95ecdf9 100644 --- a/ui/views/controls/label.h +++ b/ui/views/controls/label.h
@@ -35,6 +35,12 @@ public: METADATA_HEADER(Label); + enum MenuCommands { + kCopy = 1, + kSelectAll, + kLastCommandId = kSelectAll, + }; + // Helper to construct a Label that doesn't use the views typography spec. // Using this causes Label to obtain colors from ui::NativeTheme and line // spacing from gfx::FontList::GetHeight().
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc index d3f01a1..763a169 100644 --- a/ui/views/controls/label_unittest.cc +++ b/ui/views/controls/label_unittest.cc
@@ -1384,38 +1384,38 @@ label()->SetText(ASCIIToUTF16("Label context menu")); label()->SizeToPreferredSize(); - // A non-selectable label would not show a context menu and both COPY and - // SELECT_ALL context menu items should be disabled for it. - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); + // A non-selectable label should not show a context menu and both copy and + // select-all context menu items should be disabled for it. + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kCopy)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kSelectAll)); - // For a selectable label with no selection, only SELECT_ALL should be + // For a selectable label with no selection, only kSelectAll should be // enabled. ASSERT_TRUE(label()->SetSelectable(true)); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); - EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kCopy)); + EXPECT_TRUE(IsMenuCommandEnabled(Label::MenuCommands::kSelectAll)); - // For a selectable label with a selection, both COPY and SELECT_ALL should be - // enabled. + // For a selectable label with a selection, both copy and select-all should + // be enabled. label()->SelectRange(gfx::Range(0, 4)); - EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_COPY)); - EXPECT_TRUE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); - // Ensure unsupported commands like PASTE are not enabled. - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_PASTE)); + EXPECT_TRUE(IsMenuCommandEnabled(Label::MenuCommands::kCopy)); + EXPECT_TRUE(IsMenuCommandEnabled(Label::MenuCommands::kSelectAll)); + // Ensure unsupported commands are not enabled. + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kLastCommandId + 1)); - // An obscured label would not show a context menu and both COPY and - // SELECT_ALL should be disabled for it. + // An obscured label would not show a context menu and both copy and + // select-all should be disabled for it. label()->SetObscured(true); EXPECT_FALSE(label()->GetSelectable()); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kCopy)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kSelectAll)); label()->SetObscured(false); - // For an empty label, both COPY and SELECT_ALL should be disabled. + // For an empty label, both copy and select-all should be disabled. label()->SetText(base::string16()); ASSERT_TRUE(label()->SetSelectable(true)); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY)); - EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kCopy)); + EXPECT_FALSE(IsMenuCommandEnabled(Label::MenuCommands::kSelectAll)); } } // namespace views
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 61b11e53..c1d5e3e4 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -215,20 +215,20 @@ ui::TextEditCommand GetTextEditCommandFromMenuCommand(int command_id, bool has_selection) { switch (command_id) { - case IDS_APP_UNDO: + case Textfield::kUndo: return ui::TextEditCommand::UNDO; - case IDS_APP_CUT: + case Textfield::kCut: return ui::TextEditCommand::CUT; - case IDS_APP_COPY: + case Textfield::kCopy: return ui::TextEditCommand::COPY; - case IDS_APP_PASTE: + case Textfield::kPaste: return ui::TextEditCommand::PASTE; - case IDS_APP_DELETE: + case Textfield::kDelete: // The DELETE menu action only works in case of an active selection. if (has_selection) return ui::TextEditCommand::DELETE_FORWARD; break; - case IDS_APP_SELECT_ALL: + case Textfield::kSelectAll: return ui::TextEditCommand::SELECT_ALL; } return ui::TextEditCommand::INVALID_COMMAND; @@ -1377,23 +1377,23 @@ bool Textfield::GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) const { switch (command_id) { - case IDS_APP_UNDO: + case kUndo: *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_PLATFORM_ACCELERATOR); return true; - case IDS_APP_CUT: + case kCut: *accelerator = ui::Accelerator(ui::VKEY_X, ui::EF_PLATFORM_ACCELERATOR); return true; - case IDS_APP_COPY: + case kCopy: *accelerator = ui::Accelerator(ui::VKEY_C, ui::EF_PLATFORM_ACCELERATOR); return true; - case IDS_APP_PASTE: + case kPaste: *accelerator = ui::Accelerator(ui::VKEY_V, ui::EF_PLATFORM_ACCELERATOR); return true; - case IDS_APP_SELECT_ALL: + case kSelectAll: *accelerator = ui::Accelerator(ui::VKEY_A, ui::EF_PLATFORM_ACCELERATOR); return true; @@ -2339,15 +2339,14 @@ context_menu_contents_.reset(); context_menu_contents_ = std::make_unique<ui::SimpleMenuModel>(this); - context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO); + context_menu_contents_->AddItemWithStringId(kUndo, IDS_APP_UNDO); context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); - context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); - context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); - context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); - context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); + context_menu_contents_->AddItemWithStringId(kCut, IDS_APP_CUT); + context_menu_contents_->AddItemWithStringId(kCopy, IDS_APP_COPY); + context_menu_contents_->AddItemWithStringId(kPaste, IDS_APP_PASTE); + context_menu_contents_->AddItemWithStringId(kDelete, IDS_APP_DELETE); context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); - context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, - IDS_APP_SELECT_ALL); + context_menu_contents_->AddItemWithStringId(kSelectAll, IDS_APP_SELECT_ALL); // If the controller adds menu commands, also override ExecuteCommand() and // IsCommandIdEnabled() as appropriate, for the commands added.
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h index 21bafd3..5dce3b04 100644 --- a/ui/views/controls/textfield/textfield.h +++ b/ui/views/controls/textfield/textfield.h
@@ -75,6 +75,13 @@ public: METADATA_HEADER(Textfield); + enum MenuCommands { + kUndo = kLastTouchEditableCommandId + 1, + kDelete, + kSelectAll, + kLastCommandId = kSelectAll, + }; + // Returns the text cursor blink time, or 0 for no blinking. static base::TimeDelta GetCaretBlinkInterval();
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index 4a7a614..8075c29 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -1283,11 +1283,11 @@ SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "foo"); // Cut and copy should be disabled. - EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT)); - textfield_->ExecuteCommand(IDS_APP_CUT, 0); + EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kCut)); + textfield_->ExecuteCommand(Textfield::kCut, 0); SendKeyEvent(ui::VKEY_X, false, true); - EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY)); - textfield_->ExecuteCommand(IDS_APP_COPY, 0); + EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kCopy)); + textfield_->ExecuteCommand(Textfield::kCopy, 0); SendKeyEvent(ui::VKEY_C, false, true); SendAlternateCopy(); EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); @@ -1297,8 +1297,8 @@ SendKeyEvent(ui::VKEY_DELETE, true, false); // Paste should work normally. - EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE)); - textfield_->ExecuteCommand(IDS_APP_PASTE, 0); + EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kPaste)); + textfield_->ExecuteCommand(Textfield::kPaste, 0); SendKeyEvent(ui::VKEY_V, false, true); SendAlternatePaste(); EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); @@ -1964,24 +1964,24 @@ // Cut should be disabled. SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test"); - EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT)); - textfield_->ExecuteCommand(IDS_APP_CUT, 0); + EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kCut)); + textfield_->ExecuteCommand(Textfield::kCut, 0); SendKeyEvent(ui::VKEY_X, false, true); SendAlternateCut(); EXPECT_STR_EQ("Test", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); EXPECT_STR_EQ("read only", textfield_->GetText()); // Paste should be disabled. - EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE)); - textfield_->ExecuteCommand(IDS_APP_PASTE, 0); + EXPECT_FALSE(textfield_->IsCommandIdEnabled(Textfield::kPaste)); + textfield_->ExecuteCommand(Textfield::kPaste, 0); SendKeyEvent(ui::VKEY_V, false, true); SendAlternatePaste(); EXPECT_STR_EQ("read only", textfield_->GetText()); // Copy should work normally. SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test"); - EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY)); - textfield_->ExecuteCommand(IDS_APP_COPY, 0); + EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCopy)); + textfield_->ExecuteCommand(Textfield::kCopy, 0); EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "Test"); SendKeyEvent(ui::VKEY_C, false, true); @@ -2297,11 +2297,11 @@ TEST_F(TextfieldTest, CutCopyPaste) { InitTextfield(); - // Ensure IDS_APP_CUT cuts. + // Ensure kCut cuts. textfield_->SetText(ASCIIToUTF16("123")); textfield_->SelectAll(false); - EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT)); - textfield_->ExecuteCommand(IDS_APP_CUT, 0); + EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCut)); + textfield_->ExecuteCommand(Textfield::kCut, 0); EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); EXPECT_STR_EQ("", textfield_->GetText()); EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard()); @@ -2337,11 +2337,11 @@ EXPECT_STR_EQ("123", textfield_->GetText()); EXPECT_EQ(ui::ClipboardBuffer::kMaxValue, GetAndResetCopiedToClipboard()); - // Ensure IDS_APP_COPY copies. + // Ensure kCopy copies. textfield_->SetText(ASCIIToUTF16("789")); textfield_->SelectAll(false); - EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY)); - textfield_->ExecuteCommand(IDS_APP_COPY, 0); + EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kCopy)); + textfield_->ExecuteCommand(Textfield::kCopy, 0); EXPECT_STR_EQ("789", GetClipboardText(ui::ClipboardBuffer::kCopyPaste)); EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard()); @@ -2363,12 +2363,12 @@ EXPECT_STR_EQ("345", textfield_->GetText()); EXPECT_EQ(ui::ClipboardBuffer::kCopyPaste, GetAndResetCopiedToClipboard()); - // Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes; + // Ensure kPaste, [Ctrl]+[V], and [Shift]+[Insert] pastes; // also ensure that [Ctrl]+[Alt]+[V] does nothing. SetClipboardText(ui::ClipboardBuffer::kCopyPaste, "abc"); textfield_->SetText(base::string16()); - EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE)); - textfield_->ExecuteCommand(IDS_APP_PASTE, 0); + EXPECT_TRUE(textfield_->IsCommandIdEnabled(Textfield::kPaste)); + textfield_->ExecuteCommand(Textfield::kPaste, 0); EXPECT_STR_EQ("abc", textfield_->GetText()); SendKeyEvent(ui::VKEY_V, false, true); EXPECT_STR_EQ("abcabc", textfield_->GetText());
diff --git a/ui/views/touchui/touch_selection_menu_views.cc b/ui/views/touchui/touch_selection_menu_views.cc index ca02bef4..8b014f1 100644 --- a/ui/views/touchui/touch_selection_menu_views.cc +++ b/ui/views/touchui/touch_selection_menu_views.cc
@@ -10,6 +10,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/pointer/touch_editing_controller.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/canvas.h" @@ -25,7 +26,15 @@ namespace views { namespace { -constexpr int kMenuCommands[] = {IDS_APP_CUT, IDS_APP_COPY, IDS_APP_PASTE}; +struct MenuCommand { + int command_id; + int message_id; +} kMenuCommands[] = { + {ui::TouchEditable::kCut, IDS_APP_CUT}, + {ui::TouchEditable::kCopy, IDS_APP_COPY}, + {ui::TouchEditable::kPaste, IDS_APP_PASTE}, +}; + constexpr int kSpacingBetweenButtons = 2; constexpr int kEllipsesButtonTag = -1; @@ -95,8 +104,8 @@ const ui::TouchSelectionMenuClient* client) { DCHECK(client); - const auto is_enabled = [client](int command) { - return client->IsCommandIdEnabled(command); + const auto is_enabled = [client](MenuCommand command) { + return client->IsCommandIdEnabled(command.command_id); }; return std::any_of(std::cbegin(kMenuCommands), std::cend(kMenuCommands), is_enabled); @@ -113,12 +122,12 @@ TouchSelectionMenuViews::~TouchSelectionMenuViews() = default; void TouchSelectionMenuViews::CreateButtons() { - for (int command_id : kMenuCommands) { - if (!client_->IsCommandIdEnabled(command_id)) + for (const auto& command : kMenuCommands) { + if (!client_->IsCommandIdEnabled(command.command_id)) continue; - Button* button = - CreateButton(l10n_util::GetStringUTF16(command_id), command_id); + Button* button = CreateButton(l10n_util::GetStringUTF16(command.message_id), + command.command_id); AddChildView(button); }
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index 16294076..429c47dc 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -2012,21 +2012,21 @@ // normal->SelectAll(false); - normal->ExecuteCommand(IDS_APP_CUT, 0); + normal->ExecuteCommand(Textfield::kCut, 0); base::string16 result; clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); EXPECT_EQ(kNormalText, result); normal->SetText(kNormalText); // Let's revert to the original content. read_only->SelectAll(false); - read_only->ExecuteCommand(IDS_APP_CUT, 0); + read_only->ExecuteCommand(Textfield::kCut, 0); result.clear(); clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); // Cut should have failed, so the clipboard content should not have changed. EXPECT_EQ(kNormalText, result); password->SelectAll(false); - password->ExecuteCommand(IDS_APP_CUT, 0); + password->ExecuteCommand(Textfield::kCut, 0); result.clear(); clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); // Cut should have failed, so the clipboard content should not have changed. @@ -2038,19 +2038,19 @@ // Start with |read_only| to observe a change in clipboard text. read_only->SelectAll(false); - read_only->ExecuteCommand(IDS_APP_COPY, 0); + read_only->ExecuteCommand(Textfield::kCopy, 0); result.clear(); clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); EXPECT_EQ(kReadOnlyText, result); normal->SelectAll(false); - normal->ExecuteCommand(IDS_APP_COPY, 0); + normal->ExecuteCommand(Textfield::kCopy, 0); result.clear(); clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); EXPECT_EQ(kNormalText, result); password->SelectAll(false); - password->ExecuteCommand(IDS_APP_COPY, 0); + password->ExecuteCommand(Textfield::kCopy, 0); result.clear(); clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result); // Text cannot be copied from an obscured field; the clipboard won't change. @@ -2062,18 +2062,18 @@ // Attempting to paste kNormalText in a read-only text-field should fail. read_only->SelectAll(false); - read_only->ExecuteCommand(IDS_APP_PASTE, 0); + read_only->ExecuteCommand(Textfield::kPaste, 0); EXPECT_EQ(kReadOnlyText, read_only->GetText()); password->SelectAll(false); - password->ExecuteCommand(IDS_APP_PASTE, 0); + password->ExecuteCommand(Textfield::kPaste, 0); EXPECT_EQ(kNormalText, password->GetText()); // Copy from |read_only| to observe a change in the normal textfield text. read_only->SelectAll(false); - read_only->ExecuteCommand(IDS_APP_COPY, 0); + read_only->ExecuteCommand(Textfield::kCopy, 0); normal->SelectAll(false); - normal->ExecuteCommand(IDS_APP_PASTE, 0); + normal->ExecuteCommand(Textfield::kPaste, 0); EXPECT_EQ(kReadOnlyText, normal->GetText()); widget->CloseNow(); }
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java index 3551667..9777941 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java
@@ -61,6 +61,8 @@ "link_with_intent_to_chrome_in_new_tab.html"; private static final String PAGE_THAT_INTENTS_TO_CHROME_ON_LOAD_FILE = "page_that_intents_to_chrome_on_load.html"; + private static final String LINK_TO_PAGE_THAT_INTENTS_TO_CHROME_ON_LOAD_FILE = + "link_to_page_that_intents_to_chrome_on_load.html"; // The test server handles "echo" with a response containing "Echo" :). private final String mTestServerSiteUrl = mActivityTestRule.getTestServer().getURL("/echo"); @@ -395,4 +397,50 @@ Assert.assertEquals(INTENT_TO_CHROME_ACTION, intent.getAction()); Assert.assertEquals(INTENT_TO_CHROME_DATA_STRING, intent.getDataString()); } + + /** + * Tests the following flow: + * - The user clicks on a link + * - This link goes to a page that loads a handleable intent in onload() + * This flow should result in the external intent being launched rather than blocked, + * because the initial navigation to the page did not occur via user typing. + */ + @Test + @SmallTest + public void testUserClicksLinkToPageWithExternalIntentLaunchedViaOnLoad() throws Throwable { + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL); + IntentInterceptor intentInterceptor = new IntentInterceptor(); + activity.setIntentInterceptor(intentInterceptor); + + String url = + mActivityTestRule.getTestDataURL(LINK_TO_PAGE_THAT_INTENTS_TO_CHROME_ON_LOAD_FILE); + + mActivityTestRule.navigateAndWait(url); + + // Clicking on the link on this page should result in a navigation to the page that loads an + // intent in onLoad(), followed by a launching of that intent. + Tab tab = mActivityTestRule.getActivity().getTab(); + String finalUrl = + mActivityTestRule.getTestDataURL(PAGE_THAT_INTENTS_TO_CHROME_ON_LOAD_FILE); + NavigationWaiter waiter = + new NavigationWaiter(finalUrl, tab, /*expectFailure=*/false, /*waitForPaint=*/true); + + mActivityTestRule.executeScriptSync( + "document.onclick = function() {document.getElementById('link').click()}", + true /* useSeparateIsolate */); + EventUtils.simulateTouchCenterOfView( + mActivityTestRule.getActivity().getWindow().getDecorView()); + + waiter.waitForNavigation(); + + intentInterceptor.waitForIntent(); + + // The current URL should not have changed, and the intent should have been launched. + Assert.assertEquals(finalUrl, mActivityTestRule.getCurrentDisplayUrl()); + Intent intent = intentInterceptor.mLastIntent; + Assert.assertNotNull(intent); + Assert.assertEquals(INTENT_TO_CHROME_PACKAGE, intent.getPackage()); + Assert.assertEquals(INTENT_TO_CHROME_ACTION, intent.getAction()); + Assert.assertEquals(INTENT_TO_CHROME_DATA_STRING, intent.getDataString()); + } }
diff --git a/weblayer/test/data/link_to_page_that_intents_to_chrome_on_load.html b/weblayer/test/data/link_to_page_that_intents_to_chrome_on_load.html new file mode 100644 index 0000000..d5e024b --- /dev/null +++ b/weblayer/test/data/link_to_page_that_intents_to_chrome_on_load.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> +</head> +<body> + <a id='link' href='/weblayer/test/data/page_that_intents_to_chrome_on_load.html'> + Click to go to page that intents to Chrome on load +</a> +</body> +</html>