diff --git a/DEPS b/DEPS index 985206c..545f7eb 100644 --- a/DEPS +++ b/DEPS
@@ -116,11 +116,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '8b35379ae1f1b223385a1c566628eb9a33a5683c', + 'skia_revision': 'aa27a834ba5dae87968e63e1d62cd1c2eaea6e26', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'fcb0f91c52a8f4ba50037f9b5bb660ab51e7dafe', + 'v8_revision': '2b4710f3bfd4ac8944e9f047537592b9cb421199', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -128,7 +128,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': '37297a4f14406f49031b6855d2d8fa7ad881fd1b', + 'angle_revision': '3d86e89bce7abacff20285c0d6e8525d9ef0ce60', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -140,7 +140,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '0e8346b53d7a5c81a53bb9832dd2168bde991a17', + 'pdfium_revision': '436c9f1a888723d21bee8c5f9cadab0c2ddbf32f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -176,7 +176,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': '8c035b35abf8db181ae20d6e3a1f0e4c30c9f489', + 'catapult_revision': '6b1f256782ebaadea9b55fe1f40986d0312e3005', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -1009,7 +1009,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '688679325c646668984dc4a3be284ee3178ac02c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '4c7f72c9764e3f1c3a59692754d4aed877650690', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1161,7 +1161,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'aed3070ad40c02d2298e6603a6cce8bb91f320c7', + Var('webrtc_git') + '/src.git' + '@' + 'ee49f7087f93aacffb887ac7b5ac75ff842b501a', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1192,7 +1192,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5f64f594fd65406a8de971dc4d7891b22b48adfd', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f742ea8148139f76912d7493a1776b285afb57c9', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/aapt2.config b/android_webview/aapt2.config new file mode 100644 index 0000000..6e6b76b --- /dev/null +++ b/android_webview/aapt2.config
@@ -0,0 +1 @@ +string/license_activity_title#no_obfuscate
diff --git a/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java b/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java index 7427d0d..f7a4678 100644 --- a/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java +++ b/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java
@@ -29,6 +29,9 @@ String.format("content://%s.%s", packageName, LICENSES_URI_SUFFIX); intent.setDataAndType(Uri.parse(licenseUri), LICENSES_CONTENT_TYPE); intent.addCategory(Intent.CATEGORY_DEFAULT); + // Resources are accessed via getIdentifier because resource ids in the standalone system + // webview apk have incorrect package_ids. Accessing resources via getIdentifier needs to be + // whitelisted in //android_webview/aapt2.config. see https://crbug.com/894208 final int titleId = getResources().getIdentifier("license_activity_title", "string", packageName); if (titleId != 0) {
diff --git a/ash/components/fast_ink/fast_ink_view.cc b/ash/components/fast_ink/fast_ink_view.cc index 085756a..8ee4652 100644 --- a/ash/components/fast_ink/fast_ink_view.cc +++ b/ash/components/fast_ink/fast_ink_view.cc
@@ -159,7 +159,8 @@ gfx::Rect(holder->last_frame_size_in_pixels_), gfx::Transform()); frame.render_pass_list.push_back(std::move(pass)); - holder->frame_sink_->SubmitCompositorFrame(std::move(frame)); + holder->frame_sink_->SubmitCompositorFrame(std::move(frame), + /*show_hit_test_borders=*/false); // Delete sink holder immediately if not waiting for exported resources to // be reclaimed. @@ -188,7 +189,8 @@ exported_resources_[resource_id] = std::move(resource); last_frame_size_in_pixels_ = frame.size_in_pixels(); last_frame_device_scale_factor_ = frame.metadata.device_scale_factor; - frame_sink_->SubmitCompositorFrame(std::move(frame)); + frame_sink_->SubmitCompositorFrame(std::move(frame), + /*show_hit_test_borders=*/false); } void DamageExportedResources() {
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index c301256..e0fac63 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -12,7 +12,6 @@ #include "ash/login/ui/lock_window.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" -#include "ash/shelf/shelf.h" #include "ash/shelf/shelf_constants.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" @@ -374,35 +373,6 @@ return highlight; } -void TrayBackgroundView::PaintButtonContents(gfx::Canvas* canvas) { - if (shelf()->GetBackgroundType() == - ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT || - !separator_visible_) { - return; - } - // In the given |canvas|, for a horizontal shelf draw a separator line to the - // right or left of the TrayBackgroundView when the system is LTR or RTL - // aligned, respectively. For a vertical shelf draw the separator line - // underneath the items instead. - const gfx::Rect local_bounds = GetLocalBounds(); - const SkColor color = SkColorSetA(SK_ColorWHITE, 0x4D); - const int shelf_size = ShelfConstants::shelf_size(); - const int separator_width = ash::TrayConstants::separator_width(); - - if (shelf_->IsHorizontalAlignment()) { - const gfx::PointF point( - base::i18n::IsRTL() ? 0 : (local_bounds.width() - separator_width), - (shelf_size - kTrayItemSize) / 2); - const gfx::Vector2dF vector(0, kTrayItemSize); - canvas->Draw1pxLine(point, point + vector, color); - } else { - const gfx::PointF point((shelf_size - kTrayItemSize) / 2, - local_bounds.height() - separator_width); - const gfx::Vector2dF vector(kTrayItemSize, 0); - canvas->Draw1pxLine(point, point + vector, color); - } -} - void TrayBackgroundView::ProcessGestureEventForBubble(ui::GestureEvent* event) { if (drag_controller()) drag_controller_->ProcessGestureEvent(event, this);
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h index 65946de..dd64e05 100644 --- a/ash/system/tray/tray_background_view.h +++ b/ash/system/tray/tray_background_view.h
@@ -57,7 +57,6 @@ std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() const override; - void PaintButtonContents(gfx::Canvas* canvas) override; // TrayBubbleView::Delegate: void ProcessGestureEventForBubble(ui::GestureEvent* event) override;
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 189f888c..1fb740c 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc
@@ -420,6 +420,9 @@ size_t bucket_count = ranges->bucket_count(); // Temporary for https://crbug.com/836238 + double log_max_copy = log_max; + debug::Alias(&log_max_copy); + CHECK_EQ(maximum, static_cast<Sample>(std::round(exp(log_max_copy)))); uint32_t checksum = static_cast<uint32_t>(bucket_count + 1); checksum = Crc32(checksum, 0); checksum = Crc32(checksum, current); @@ -448,6 +451,9 @@ ranges->ResetChecksum(); checksum = Crc32(checksum, HistogramBase::kSampleType_MAX); CHECK_EQ(checksum, ranges->checksum()); + log_max_copy = log_max; + debug::Alias(&log_max_copy); + CHECK_EQ(maximum, static_cast<Sample>(std::round(exp(log_max_copy)))); } // static
diff --git a/base/task/task_scheduler/task_tracker.cc b/base/task/task_scheduler/task_tracker.cc index 32ffff9..8cfe827 100644 --- a/base/task/task_scheduler/task_tracker.cc +++ b/base/task/task_scheduler/task_tracker.cc
@@ -133,12 +133,6 @@ : 0]; } -// Maximum number of BLOCK_SHUTDOWN tasks that can be posted during shutdown. If -// that many BLOCK_SHUTDOWN tasks are posted during shutdown, it is possible -// that buggy code is posting an infinite number of tasks and that shutdown will -// never complete. The mitigation is to induce a crash. -constexpr int kMaxBlockShutdownTasksPostedDuringShutdown = 1000; - // Returns the maximum number of TaskPriority::BEST_EFFORT sequences that can be // scheduled concurrently based on command line flags. int GetMaxNumScheduledBestEffortSequences() { @@ -663,7 +657,6 @@ // This method can only be called once. DCHECK(!shutdown_event_); - DCHECK(!num_block_shutdown_tasks_posted_during_shutdown_); DCHECK(!state_->HasShutdownStarted()); shutdown_event_ = std::make_unique<WaitableEvent>(); @@ -783,10 +776,6 @@ state_->DecrementNumTasksBlockingShutdown(); return false; } - - ++num_block_shutdown_tasks_posted_during_shutdown_; - CHECK_LT(num_block_shutdown_tasks_posted_during_shutdown_, - kMaxBlockShutdownTasksPostedDuringShutdown); } return true;
diff --git a/base/task/task_scheduler/task_tracker.h b/base/task/task_scheduler/task_tracker.h index 096c5af..83408f8 100644 --- a/base/task/task_scheduler/task_tracker.h +++ b/base/task/task_scheduler/task_tracker.h
@@ -396,9 +396,6 @@ bool execution_fence_enabled_ = false; #endif - // Number of BLOCK_SHUTDOWN tasks posted during shutdown. - HistogramBase::Sample num_block_shutdown_tasks_posted_during_shutdown_ = 0; - // Enforces that |max_scheduled_sequences| and // |max_scheduled_sequences_before_fence| in PreemptedState are only written // on the main sequence (determined by the first call to
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index ce24941..c1d62a8 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -329,8 +329,9 @@ resource_infos = resource_apk.infolist() # 1. AndroidManifest.xml - assert resource_infos[0].filename == 'AndroidManifest.xml' - copy_resource(resource_infos[0], out_dir=apk_manifest_dir) + copy_resource( + resource_apk.getinfo('AndroidManifest.xml'), + out_dir=apk_manifest_dir) # 2. Assets if options.write_asset_list: @@ -380,8 +381,9 @@ build_utils.AddToZipHermetic(out_apk, apk_path, data='') # 5. Resources - for info in resource_infos[1:]: - copy_resource(info) + for info in resource_infos: + if info.filename != 'AndroidManifest.xml': + copy_resource(info) # 6. Java resources that should be accessible via # Class.getResourceAsStream(), in particular parts of Emma jar.
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py index cbc2930..56a827e3 100755 --- a/build/android/gyp/compile_resources.py +++ b/build/android/gyp/compile_resources.py
@@ -141,6 +141,17 @@ action='store_true', help='Whether to strip xml namespaces from processed ' 'xml resources') + input_opts.add_argument( + '--resources-config-path', help='Path to aapt2 resources config file.') + input_opts.add_argument( + '--optimize-resources', + default=False, + action='store_true', + help='Whether to run the `aapt2 optimize` step on the resources.') + input_opts.add_argument( + '--unoptimized-resources-path', + help='Path to output the intermediate apk before running ' + '`aapt2 optimize`.') input_opts.add_argument( '--check-resources-pkg-id', type=_PackageIdArgument, @@ -306,7 +317,6 @@ '--version-name', options.version_name, '--auto-add-overlay', '--no-version-vectors', - '-o', options.apk_path, ] for j in options.include_resources: @@ -481,7 +491,11 @@ partial_path = os.path.join(partials_dir, dirname + '.zip') compile_command = (partial_compile_command + ['--dir', directory, '-o', partial_path]) - build_utils.CheckOutput(compile_command) + build_utils.CheckOutput( + compile_command, + stderr_filter=lambda output: + build_utils.FilterLines( + output, r'ignoring configuration .* for styleable')) # Sorting the files in the partial ensures deterministic output from the # aapt2 link step which uses order of files in the partial. @@ -541,7 +555,15 @@ for directory in dep_subdirs: renamed_paths.update(_MoveImagesToNonMdpiFolders(directory)) + if options.optimize_resources: + if options.unoptimized_resources_path: + unoptimized_apk_path = options.unoptimized_resources_path + else: + unoptimized_apk_path = os.path.join(gen_dir, 'intermediate.ap_') + else: + unoptimized_apk_path = options.apk_path link_command = _CreateLinkApkArgs(options) + link_command += ['-o', unoptimized_apk_path] link_command += ['--output-text-symbols', r_txt_path] # TODO(digit): Is this below actually required for R.txt generation? link_command += ['--java', gen_dir] @@ -557,10 +579,69 @@ # Also creates R.txt build_utils.CheckOutput( link_command, print_stdout=False, print_stderr=False) + + if options.optimize_resources: + _OptimizeApk(options, temp_dir, unoptimized_apk_path, r_txt_path) + _CreateResourceInfoFile( renamed_paths, options.apk_info_path, options.dependencies_res_zips) +def _OptimizeApk(options, temp_dir, unoptimized_apk_path, r_txt_path): + """Optimize intermediate .ap_ file with aapt2. + + Args: + options: The command-line options tuple. E.g. the generated apk + will be written to |options.apk_path|. + temp_dir: A temporary directory. + unoptimized_apk_path: path of the apk to optimize. + r_txt_path: path to the R.txt file of the unoptimized apk. + """ + # Resources of type ID are references to UI elements/views. They are used by + # UI automation testing frameworks. They are kept in so that they dont break + # tests, even though they may not actually be used during runtime. See + # https://crbug.com/900993 + id_resources = _ExtractIdResources(r_txt_path) + gen_config_path = os.path.join(temp_dir, 'aapt2.config') + if options.resources_config_path: + shutil.copyfile(options.resources_config_path, gen_config_path) + with open(gen_config_path, 'a+') as config: + for resource in id_resources: + config.write('{}#no_obfuscate\n'.format(resource)) + + # Optimize the resources.arsc file by obfuscating resource names and only + # allow usage via R.java constant. + optimize_command = [ + options.aapt2_path, + 'optimize', + '--enable-resource-obfuscation', + '-o', + options.apk_path, + '--resources-config-path', + gen_config_path, + unoptimized_apk_path, + ] + build_utils.CheckOutput( + optimize_command, print_stdout=False, print_stderr=False) + + +def _ExtractIdResources(rtxt_path): + """Extract resources of type ID from the R.txt file + + Args: + rtxt_path: Path to R.txt file with all the resources + Returns: + List of id resources in the form of id/<resource_name> + """ + id_resources = [] + with open(rtxt_path) as rtxt: + for line in rtxt: + if ' id ' in line: + resource_name = line.split()[2] + id_resources.append('id/{}'.format(resource_name)) + return id_resources + + def _WriteFinalRTxtFile(options, aapt_r_txt_path): """Determine final R.txt and return its location. @@ -639,25 +720,27 @@ # Order of these must match order specified in GN so that the correct one # appears first in the depfile. possible_output_paths = [ - options.apk_path, - options.apk_path + '.info', - options.r_text_out, - options.srcjar_out, - options.proguard_file, - options.proguard_file_main_dex, + options.apk_path, + options.apk_path + '.info', + options.r_text_out, + options.srcjar_out, + options.proguard_file, + options.proguard_file_main_dex, + options.unoptimized_resources_path, ] output_paths = [x for x in possible_output_paths if x] # List python deps in input_strings rather than input_paths since the contents # of them does not change what gets written to the depsfile. input_strings = options.extra_res_packages + [ - options.shared_resources, - options.resource_blacklist_regex, - options.resource_blacklist_exceptions, - str(options.debuggable), - str(options.png_to_webp), - str(options.support_zh_hk), - str(options.no_xml_namespaces), + options.shared_resources, + options.resource_blacklist_regex, + options.resource_blacklist_exceptions, + str(options.debuggable), + str(options.png_to_webp), + str(options.support_zh_hk), + str(options.no_xml_namespaces), + str(options.optimize_resources), ] input_strings.extend(_CreateLinkApkArgs(options)) @@ -669,11 +752,12 @@ possible_input_paths = [ - options.aapt_path, - options.aapt2_path, - options.android_manifest, - debug_temp_resources_dir, - options.shared_resources_whitelist, + options.aapt_path, + options.aapt2_path, + options.android_manifest, + debug_temp_resources_dir, + options.shared_resources_whitelist, + options.resources_config_path, ] possible_input_paths += options.include_resources input_paths = [x for x in possible_input_paths if x]
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 5e7636ae..d49941e04 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1981,14 +1981,15 @@ outputs = [] _android_aapt_path = android_default_aapt_path + _android_aapt2_path = android_sdk_tools_bundle_aapt2 if (_proto_format) { - _android_aapt2_path = android_sdk_tools_bundle_aapt2 depfile = "$target_gen_dir/${invoker.target_name}_3.d" } inputs = [ invoker.build_config, _android_aapt_path, + _android_aapt2_path, ] _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) @@ -1999,19 +2000,13 @@ "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)", "--aapt-path", rebase_path(_android_aapt_path, root_build_dir), + "--aapt2-path", + rebase_path(_android_aapt2_path, root_build_dir), "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)", "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)", "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)", ] - if (_proto_format) { - inputs += [ _android_aapt2_path ] - args += [ - "--aapt2-path", - rebase_path(_android_aapt2_path, root_build_dir), - ] - } - inputs += [ invoker.android_manifest ] args += [ "--android-manifest", @@ -2048,6 +2043,25 @@ ] } + if (defined(invoker.optimize_resources) && invoker.optimize_resources) { + args += [ "--optimize-resources" ] + if (defined(invoker.resources_config_path)) { + inputs += [ invoker.resources_config_path ] + args += [ + "--resources-config-path", + rebase_path(invoker.resources_config_path, root_build_dir), + ] + } + + if (defined(invoker.unoptimized_resources_path)) { + args += [ + "--unoptimized-resources-path", + rebase_path(invoker.unoptimized_resources_path, root_build_dir), + ] + outputs += [ invoker.unoptimized_resources_path ] + } + } + # Useful to have android:debuggable in the manifest even for Release # builds. Just omit it for officai if (debuggable_apks) { @@ -2501,6 +2515,13 @@ get_label_info(_incremental_compile_resources_target_name, "target_gen_dir") + "/AndroidManifest.xml" + if (defined(invoker.unoptimized_resources_path)) { + _incremental_packaged_resources_path = + invoker.unoptimized_resources_path + } else { + _incremental_packaged_resources_path = invoker.packaged_resources_path + } + _rebased_build_config = rebase_path(invoker.assets_build_config, root_build_dir) @@ -2511,7 +2532,7 @@ inputs = [ _android_manifest, invoker.assets_build_config, - invoker.packaged_resources_path, + _incremental_packaged_resources_path, ] outputs = [ # Output the non-compiled manifest for easy debugging (as opposed to @@ -2526,7 +2547,7 @@ "--out-manifest", rebase_path(_incremental_android_manifest, root_build_dir), "--in-apk", - rebase_path(invoker.packaged_resources_path, root_build_dir), + rebase_path(_incremental_packaged_resources_path, root_build_dir), "--out-apk", rebase_path(_incremental_compiled_resources_path, root_build_dir), "--aapt-path",
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index d7c9e78..527ca02 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1885,6 +1885,10 @@ # uncompressed in the APK. Must be unset or true if load_library_from_apk # is set to true. # uncompress_dex: Store final .dex files uncompressed in the apk. + # optimize_resources: True if resource names should be stripped from the + # resources.arsc file in the apk or module. + # resources_config_path: Path to the aapt2 optimize config file that tags + # resources with acceptable/non-acceptable optimizations. template("android_apk_or_module") { forward_variables_from(invoker, [ "testonly" ]) @@ -2125,6 +2129,13 @@ _android_sdk_dep = "//third_party/android_tools:android_sdk_java" } + _optimize_resources = + defined(invoker.optimize_resources) && invoker.optimize_resources + if (_optimize_resources) { + _unoptimized_resources_path = + "$target_out_dir/$_template_name.unoptimized.ap_" + } + _compile_resources_target = "${_template_name}__compile_resources" _compile_resources_rtxt_out = "${target_gen_dir}/${_compile_resources_target}_R.txt" @@ -2137,6 +2148,7 @@ "aapt_locale_whitelist", "resource_blacklist_regex", "resource_blacklist_exceptions", + "resources_config_path", "png_to_webp", "no_xml_namespaces", ]) @@ -2154,6 +2166,10 @@ proguard_file_main_dex = _generated_proguard_main_dex_config } output = _packaged_resources_path + if (_optimize_resources) { + optimize_resources = true + unoptimized_resources_path = _unoptimized_resources_path + } build_config = _build_config deps = _deps + [ @@ -2590,6 +2606,9 @@ if (_incremental_allowed) { android_manifest = _android_manifest base_path = _base_path + if (_optimize_resources) { + unoptimized_resources_path = _unoptimized_resources_path + } } # Incremental apk does not use native libs nor final dex. @@ -2863,6 +2882,7 @@ "never_incremental", "no_build_hooks", "no_xml_namespaces", + "optimize_resources", "png_to_webp", "post_process_package_resources_script", "product_version_resources_dep", @@ -2871,6 +2891,7 @@ "proguard_jar_path", "resource_blacklist_regex", "resource_blacklist_exceptions", + "resources_config_path", "secondary_abi_loadable_modules", "secondary_abi_shared_libraries", "secondary_native_lib_placeholders", @@ -2961,6 +2982,7 @@ "native_lib_version_rule", "negative_main_dex_globs", "no_xml_namespaces", + "optimize_resources", "png_to_webp", "product_version_resources_dep", "proguard_configs", @@ -2968,6 +2990,7 @@ "proguard_jar_path", "resource_blacklist_regex", "resource_blacklist_exceptions", + "resources_config_path", "secondary_abi_loadable_modules", "secondary_abi_shared_libraries", "secondary_native_lib_placeholders",
diff --git a/build/fuchsia/fidlgen_js/gen.py b/build/fuchsia/fidlgen_js/gen.py index 7f29e72..b99fd35 100755 --- a/build/fuchsia/fidlgen_js/gen.py +++ b/build/fuchsia/fidlgen_js/gen.py
@@ -115,8 +115,8 @@ self._CompileConst(c) for e in self.fidl.enum_declarations: self._CompileEnum(e) - if self.fidl.union_declarations: - raise NotImplementedError() + for u in self.fidl.union_declarations: + self._CompileUnion(u) for s in self.fidl.struct_declarations: self._CompileStruct(s) for i in self.fidl.interface_declarations: @@ -133,12 +133,19 @@ ''') - def _CompileConst(self, c): + def _CompileConst(self, const): + compound = _ParseCompoundIdentifier(const.name) + name = _CompileCompoundIdentifier(compound) + value = _CompileConstant(const.value) self.f.write('''/** - * @const {%(type)s} - */ + * @const + */ const %(name)s = %(value)s; -''' % c.to_dict()) + +''' % { + 'name': name, + 'value': value + }) def _CompileEnum(self, enum): compound = _ParseCompoundIdentifier(enum.name) @@ -156,6 +163,85 @@ self.f.write('};\n') self.f.write('const _kTT_%(name)s = _kTT_%(type)s;\n\n' % data) + def _CompileUnion(self, union): + compound = _ParseCompoundIdentifier(union.name) + name = _CompileCompoundIdentifier(compound) + member_names = [] + enc_cases = [] + for i, m in enumerate(union.members): + member_name = _ChangeIfReserved(m.name) + member_names.append(member_name) + member_type = self._CompileType(m.type) + enc_cases.append('''\ + case %(index)s: + _kTT_%(member_type)s.enc(e, o + 4, v.%(member_name)s); + break;''' % { + 'index': i, + 'member_type': member_type, + 'member_name': member_name, + }) + + self.f.write('''\ +const _kTT_%(name)s = { + enc: function(e, o, v) { + if (v.$tag === $fidl__kInvalidUnionTag) throw "invalid tag"; + e.data.setUint32(o, v.$tag, $fidl__kLE); + switch (v.$tag) { +%(enc_cases)s + } + }, + dec: function(d, o) { + throw 'not implemented crbug.com/883496' + }, +}; + +const _kTT_%(name)s_Nullable = { + enc: function(e, o, v) { + e.data.setUint32(o, v ? 0xffffffff : 0, $fidl__kLE); + e.data.setUint32(o + 4, v ? 0xffffffff : 0, $fidl__kLE); + e.outOfLine.push([function() { + var start = e.alloc(%(size)s); + _kTT_%(name)s.enc(e, start, v); + }]); + }, + dec: function(d, o) { + throw 'not implemented crbug.com/883496' + }, +}; + +/** + * @constructor + */ +function %(name)s() { this.reset(); } + +%(name)s.prototype.reset = function(i) { + this.$tag = (i === undefined) ? $fidl__kInvalidUnionTag : i; +''' % { + 'name': name, + 'size': union.size, + 'enc_cases': '\n'.join(enc_cases), + }) + for m in member_names: + self.f.write(' this.%s = null;\n' % m) + self.f.write('}\n\n') + + for i, m in enumerate(member_names): + self.f.write('''\ +%(name)s.prototype.set_%(member_name)s = function(v) { + this.reset(%(index)s); + this.%(member_name)s = v; +}; + +%(name)s.prototype.is_%(member_name)s = function() { + return this.$tag === %(index)s; +}; + +''' % { + 'name': name, + 'member_name': m, + 'index': i, + }) + def _CompileStruct(self, struct): compound = _ParseCompoundIdentifier(struct.name) name = _CompileCompoundIdentifier(compound) @@ -176,6 +262,12 @@ if member.maybe_default_value: value = ('(%(member_name)s !== undefined) ? %(member_name)s : ' + _CompileConstant(member.maybe_default_value)) + elif self.fidl.declarations.get(member.type.identifier) == \ + fidl.DeclarationsMap.UNION: + union_compound = _ParseCompoundIdentifier(member.type.identifier) + union_name = _CompileCompoundIdentifier(union_compound) + value = ('(%(member_name)s !== undefined) ? %(member_name)s : ' + 'new ' + + union_name + '()') self.f.write((' this.%(member_name)s = ' + value + ';\n') % {'member_name': member_name}) self.f.write('}\n\n') @@ -217,6 +309,8 @@ }) def _CompileType(self, t): + """Ensures there's a type table for the given type, and returns the stem of + its name.""" if t.kind == fidl.TypeKind.PRIMITIVE: return t.subtype elif t.kind == fidl.TypeKind.STRING: @@ -224,7 +318,37 @@ elif t.kind == fidl.TypeKind.IDENTIFIER: compound = _ParseCompoundIdentifier(t.identifier) name = _CompileCompoundIdentifier(compound) - return name + return name + ('_Nullable' if t.nullable else '') + elif t.kind == fidl.TypeKind.HANDLE: + return 'Handle' + elif t.kind == fidl.TypeKind.ARRAY: + element_ttname = self._CompileType(t.element_type) + ttname = 'ARR_%d_%s' % (t.element_count, element_ttname) + if ttname not in self.type_table_defined: + self.type_table_defined.add(ttname) + self.output_deferred_to_eof += ('''\ +const _kTT_%(ttname)s = { + enc: function(e, o, v) { + for (var i = 0; i < %(element_count)s; i++) { + _kTT_%(element_ttname)s.enc(e, o + (i * %(element_size)s), v[i]); + } + }, + dec: function(d, o) { + var result = []; + for (var i = 0; i < %(element_count)s; i++) { + result.push(_kTT_%(element_ttname)s.dec(d, o + (i * %(element_size)s))); + } + return result; + }, +}; + +''' % { + 'ttname': ttname, + 'element_ttname': element_ttname, + 'element_count': t.element_count, + 'element_size': _InlineSizeOfType(t.element_type), + }) + return ttname elif t.kind == fidl.TypeKind.VECTOR: element_ttname = self._CompileType(t.element_type) ttname = ( @@ -285,7 +409,7 @@ }) return ttname else: - raise NotImplementedError() + raise NotImplementedError(t.kind) def _GenerateJsInterfaceForInterface(self, name, interface): """Generates a JS @interface for the given FIDL interface.""" @@ -400,7 +524,7 @@ var $view = new DataView($readResult.data); - var $decoder = new $fidl_Decoder($view, []); + var $decoder = new $fidl_Decoder($view, $readResult.handles); $decoder.claimMemory(%(size)s - $fidl_kMessageHeaderSize); ''' % {'size': method.maybe_response_size}) for param, ttname in zip(method.maybe_response, type_tables):
diff --git a/build/fuchsia/fidlgen_js/runtime/fidl.mjs b/build/fuchsia/fidlgen_js/runtime/fidl.mjs index be2ff80..be7f343 100644 --- a/build/fuchsia/fidlgen_js/runtime/fidl.mjs +++ b/build/fuchsia/fidlgen_js/runtime/fidl.mjs
@@ -18,6 +18,8 @@ const $fidl__kLE = true; const $fidl__kUserspaceTxidMask = 0x7fffffff; +const $fidl__kHandlePresent = 0xffffffff; +const $fidl__kInvalidUnionTag = 0xffffffff; var $fidl__nextTxid = 1; function $fidl__align(size) { @@ -78,6 +80,13 @@ this.data = new DataView(newBuffer); }; +/** + * @param {number} handle + */ +$fidl_Encoder.prototype.addHandle = function(handle) { + this.handles.push(handle); +}; + $fidl_Encoder.prototype.messageData = function() { // Add all out of line data. var len = this.outOfLine.length; @@ -117,6 +126,8 @@ } $fidl_Decoder.prototype.claimHandle = function() { + if (this.nextHandle >= this.handles.length) + throw "Attempt to claim more handles than are available"; return this.handles[this.nextHandle++]; } @@ -157,6 +168,27 @@ dec: function(d, o) { return d.data.getUint32(o, $fidl__kLE); }, }; +const _kTT_Handle = { + enc: function(e, o, v) { + if (v === null || v === undefined) { + e.data.setUint32(o, 0, $fidl__kLE); + } else { + e.data.setUint32(o, $fidl__kHandlePresent, $fidl__kLE); + e.addHandle(v); + } + }, + dec: function(d, o) { + var $present = d.data.getUint32(o, $fidl__kLE); + if ($present === 0) { + return 0; + } else { + if ($present !== $fidl__kHandlePresent) + throw "Expected UINT32_MAX to indicate handle presence"; + return d.claimHandle(); + } + }, +}; + const _kTT_String_Nonnull = { enc: function(e, o, v) { if (v === null || v === undefined) throw "non-null string required";
diff --git a/build/fuchsia/fidlgen_js/runtime/zircon.cc b/build/fuchsia/fidlgen_js/runtime/zircon.cc index cb007c1..b5f191f 100644 --- a/build/fuchsia/fidlgen_js/runtime/zircon.cc +++ b/build/fuchsia/fidlgen_js/runtime/zircon.cc
@@ -240,7 +240,6 @@ handles.data(), handles.size(), &actual_handles); DCHECK_EQ(actual_bytes, data_size); DCHECK_EQ(actual_handles, num_handles); - CHECK_EQ(actual_handles, 0u) << "Handle passing untested"; if (status != ZX_OK) { return gin::DataObjectBuilder(args->isolate())
diff --git a/build/fuchsia/fidlgen_js/test/fidlgen_js_unittest.cc b/build/fuchsia/fidlgen_js/test/fidlgen_js_unittest.cc index 8ca5644..d575858 100644 --- a/build/fuchsia/fidlgen_js/test/fidlgen_js_unittest.cc +++ b/build/fuchsia/fidlgen_js/test/fidlgen_js_unittest.cc
@@ -5,8 +5,11 @@ #include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/internal/pending_response.h> #include <lib/fidl/cpp/internal/weak_stub_controller.h> +#include <lib/zx/log.h> +#include <zircon/syscalls/log.h> #include "base/bind.h" +#include "base/fuchsia/fuchsia_logging.h" #include "base/run_loop.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" @@ -29,6 +32,22 @@ static const char kTestBindingFile[] = "/pkg/build/fuchsia/fidlgen_js/fidl/fidljstest/js/fidl.js"; +namespace { + +zx_koid_t GetKoidForHandle(const zx::object_base& object) { + zx_info_handle_basic_t info; + zx_status_t status = + zx_object_get_info(object.get(), ZX_INFO_HANDLE_BASIC, &info, + sizeof(info), nullptr, nullptr); + if (status != ZX_OK) { + ZX_LOG(ERROR, status) << "zx_object_get_info"; + return ZX_KOID_INVALID; + } + return info.koid; +} + +} // namespace + class FidlGenJsTestShellRunnerDelegate : public gin::ShellRunnerDelegate { public: FidlGenJsTestShellRunnerDelegate() {} @@ -186,10 +205,37 @@ sat.basic.u16 = basic_struct.u16 * 2; sat.basic.u32 = basic_struct.u32 * 2; sat.later_string = "ⓣⓔⓡⓜⓘⓝⓐⓣⓞⓡ"; + for (uint64_t i = 0; i < fidljstest::ARRRR_SIZE; ++i) { + sat.arrrr[i] = static_cast<int32_t>(i * 5) - 10; + } resp(std::move(sat)); } + void PassHandles(zx::job job, PassHandlesCallback callback) override { + EXPECT_EQ(GetKoidForHandle(job), GetKoidForHandle(*zx::job::default_job())); + zx::log log; + EXPECT_EQ(zx::log::create(ZX_LOG_FLAG_READABLE, &log), ZX_OK); + unowned_log_handle_ = log.get(); + callback(std::move(log)); + } + + void ReceiveUnions(fidljstest::StructOfMultipleUnions somu) override { + EXPECT_TRUE(somu.initial.is_swb()); + EXPECT_TRUE(somu.initial.swb().some_bool); + + EXPECT_TRUE(somu.optional.get()); + EXPECT_TRUE(somu.optional->is_lswa()); + for (int i = 0; i < 32; ++i) { + EXPECT_EQ(somu.optional->lswa().components[i], i * 99); + } + + EXPECT_TRUE(somu.trailing.is_swu()); + EXPECT_EQ(somu.trailing.swu().length, 123456u); + + did_receive_union_ = true; + } + bool was_do_something_called() const { return was_do_something_called_; } int32_t received_int() const { return received_int_; } const std::string& received_msg() const { return received_msg_; } @@ -198,8 +244,12 @@ const std::string& various_msg() const { return various_msg_; } const std::vector<uint32_t>& various_stuff() const { return various_stuff_; } + zx_handle_t unowned_log_handle() const { return unowned_log_handle_; } + fidljstest::BasicStruct GetReceivedStruct() const { return basic_struct_; } + bool did_receive_union() const { return did_receive_union_; } + void CallResponseCallbacks() { for (auto& cb : response_callbacks_) { std::move(cb).Run(); @@ -216,6 +266,8 @@ std::vector<uint32_t> various_stuff_; fidljstest::BasicStruct basic_struct_; std::vector<base::OnceClosure> response_callbacks_; + zx_handle_t unowned_log_handle_; + bool did_receive_union_ = false; DISALLOW_COPY_AND_ASSIGN(TestolaImpl); }; @@ -369,7 +421,7 @@ .then(sum => { this.sum_result = sum; }) - .catch((e) => log('HOT GARBAGE: ' + e)); + .catch((e) => log('FAILED: ' + e)); )"; helper.runner().Run(source, "test.js"); @@ -407,7 +459,7 @@ this.rejected = true; }) .catch((e) => { - log('HOT GARBAGE: ' + e); + log('FAILED: ' + e); this.excepted = true; }) )"; @@ -483,8 +535,9 @@ this.result_basic_u16 = sat.basic.u16; this.result_basic_u32 = sat.basic.u32; this.result_later_string = sat.later_string; + this.result_arrrr = sat.arrrr; }) - .catch((e) => log('HOT GARBAGE: ' + e)); + .catch((e) => log('FAILED: ' + e)); )"; helper.runner().Run(source, "test.js"); @@ -507,6 +560,92 @@ EXPECT_EQ(helper.Get<unsigned int>("result_basic_u16"), 64000u); EXPECT_EQ(helper.Get<unsigned int>("result_basic_u32"), 4000000000u); EXPECT_EQ(helper.Get<std::string>("result_later_string"), "ⓣⓔⓡⓜⓘⓝⓐⓣⓞⓡ"); + // Retrieve as a vector as there's no difference in representation in JS (and + // gin already supports vector), and verify the length matches the expected + // length of the fidl array. + auto result_arrrr = helper.Get<std::vector<int32_t>>("result_arrrr"); + ASSERT_EQ(result_arrrr.size(), fidljstest::ARRRR_SIZE); + for (uint64_t i = 0; i < fidljstest::ARRRR_SIZE; ++i) { + EXPECT_EQ(result_arrrr[i], static_cast<int32_t>(i * 5) - 10); + } +} + +TEST_F(FidlGenJsTest, HandlePassing) { + v8::Isolate* isolate = instance_->isolate(); + BindingsSetupHelper helper(isolate); + + TestolaImpl testola_impl; + fidl::Binding<fidljstest::Testola> binding(&testola_impl); + binding.Bind(std::move(helper.server())); + + zx::job default_job_copy; + ASSERT_EQ(zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, + &default_job_copy), + ZX_OK); + helper.runner().global()->Set( + gin::StringToSymbol(isolate, "testJobHandle"), + gin::ConvertToV8(isolate, default_job_copy.get())); + + // TODO(crbug.com/883496): Handles wrapped in Transferrable once MessagePort + // is sorted out, and then stop treating handles as unmanaged |uint32_t|s. + std::string source = R"( + var proxy = new TestolaProxy(); + proxy.$bind(testHandle); + proxy.PassHandles(testJobHandle).then(h => { + this.debuglogHandle = h; + }).catch((e) => log('FAILED: ' + e)); + )"; + helper.runner().Run(source, "test.js"); + + // Run the message loop to send the request and receive a response. + base::RunLoop().RunUntilIdle(); + + zx_handle_t debug_handle_back_from_js = + helper.Get<uint32_t>("debuglogHandle"); + EXPECT_EQ(debug_handle_back_from_js, testola_impl.unowned_log_handle()); + + // Make sure we received the valid handle back correctly, and close it. Not + // stored into a zx::log in case it isn't valid, and to check the return value + // from closing it. + EXPECT_EQ(zx_handle_close(debug_handle_back_from_js), ZX_OK); + + // Ensure we didn't pass away our default job. + EXPECT_NE(GetKoidForHandle(*zx::job::default_job()), ZX_KOID_INVALID); +} + +TEST_F(FidlGenJsTest, UnionSend) { + v8::Isolate* isolate = instance_->isolate(); + BindingsSetupHelper helper(isolate); + + TestolaImpl testola_impl; + fidl::Binding<fidljstest::Testola> binding(&testola_impl); + binding.Bind(std::move(helper.server())); + + std::string source = R"( + var proxy = new TestolaProxy(); + proxy.$bind(testHandle); + var somu = new StructOfMultipleUnions(); + + var swb = new StructWithBool(/*some_bool*/ true); + somu.initial.set_swb(swb); + + var lswa = new LargerStructWithArray([]); + for (var i = 0; i < 32; ++i) { + lswa.components[i] = i * 99; + } + somu.optional.set_lswa(lswa); + + somu.trailing.set_swu(new StructWithUint(123456)); + + proxy.ReceiveUnions(somu); + )"; + helper.runner().Run(source, "test.js"); + + base::RunLoop().RunUntilIdle(); + + // Expectations on the contents of the union are checked in the body of + // TestolaImpl::ReceiveAUnion(). + EXPECT_TRUE(testola_impl.did_receive_union()); } int main(int argc, char** argv) {
diff --git a/build/fuchsia/fidlgen_js/test/simple.fidl b/build/fuchsia/fidlgen_js/test/simple.fidl index 01bab14..8bc2b6d 100644 --- a/build/fuchsia/fidlgen_js/test/simple.fidl +++ b/build/fuchsia/fidlgen_js/test/simple.fidl
@@ -22,12 +22,39 @@ uint32 u32 = 4000000000; }; +const uint64 ARRRR_SIZE = 32; + struct StuffAndThings { int32 count; string id; vector<int32> a_vector; BasicStruct basic; string later_string; + array<int32>:ARRRR_SIZE arrrr; +}; + +struct StructWithBool { + bool some_bool = false; +}; + +struct StructWithUint { + uint32 length; +}; + +struct LargerStructWithArray { + array<int32>:32 components; +}; + +union UnionOfStructs { + StructWithBool swb; + StructWithUint swu; + LargerStructWithArray lswa; +}; + +struct StructOfMultipleUnions { + UnionOfStructs initial; + UnionOfStructs? optional; + UnionOfStructs trailing; }; interface Testola { @@ -44,4 +71,8 @@ 6: SendAStruct(BasicStruct basic); 7: NestedStructsWithResponse(BasicStruct basic) -> (StuffAndThings resp); + + 8: PassHandles(handle<job> job) -> (handle<debuglog> debuglog); + + 9: ReceiveUnions(StructOfMultipleUnions somu); };
diff --git a/cc/debug/layer_tree_debug_state.cc b/cc/debug/layer_tree_debug_state.cc index 56b8879..6b51ff0 100644 --- a/cc/debug/layer_tree_debug_state.cc +++ b/cc/debug/layer_tree_debug_state.cc
@@ -24,6 +24,7 @@ slow_down_raster_scale_factor(0), rasterize_only_visible_content(false), show_picture_borders(false), + show_hit_test_borders(false), record_rendering_stats_(false) {} LayerTreeDebugState::LayerTreeDebugState(const LayerTreeDebugState& other) = @@ -73,6 +74,7 @@ a.slow_down_raster_scale_factor == b.slow_down_raster_scale_factor && a.rasterize_only_visible_content == b.rasterize_only_visible_content && a.show_picture_borders == b.show_picture_borders && + a.show_hit_test_borders == b.show_hit_test_borders && a.record_rendering_stats_ == b.record_rendering_stats_); } @@ -98,6 +100,8 @@ r.rasterize_only_visible_content |= b.rasterize_only_visible_content; r.show_picture_borders |= b.show_picture_borders; + r.show_hit_test_borders |= b.show_hit_test_borders; + r.record_rendering_stats_ |= b.record_rendering_stats_; return r;
diff --git a/cc/debug/layer_tree_debug_state.h b/cc/debug/layer_tree_debug_state.h index 2ea5f9c..c7438b6 100644 --- a/cc/debug/layer_tree_debug_state.h +++ b/cc/debug/layer_tree_debug_state.h
@@ -46,6 +46,8 @@ bool rasterize_only_visible_content; bool show_picture_borders; + bool show_hit_test_borders; + void SetRecordRenderingStats(bool enabled); bool RecordRenderingStats() const;
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index cd75db21..aefad53 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -720,6 +720,7 @@ // can cause activation flickering issues. So, if we're in this situation // adjust the visible rect by the the controls height. if (layer_tree_impl()->IsPendingTree() && + layer_tree_impl()->IsActivelyScrolling() && layer_tree_impl()->browser_controls_shrink_blink_size()) { viewport_rect_for_tile_priority_in_content_space_.Inset( 0, // left @@ -1559,13 +1560,30 @@ float min_contents_scale = MinimumContentsScale(); DCHECK_GT(min_contents_scale, 0.f); - ideal_page_scale_ = IsAffectedByPageScale() - ? layer_tree_impl()->current_page_scale_factor() - : 1.f; ideal_device_scale_ = layer_tree_impl()->device_scale_factor(); + if (layer_tree_impl()->PageScaleLayer()) { + ideal_page_scale_ = IsAffectedByPageScale() + ? layer_tree_impl()->current_page_scale_factor() + : 1.f; + ideal_contents_scale_ = GetIdealContentsScale(); + } else { + // This layer may be in a layer tree embedded in a hierarchy that has its + // own page scale factor. We represent that here as + // 'external_page_scale_factor', a value that affects raster scale in the + // same way that page_scale_factor does, but doesn't affect any geometry + // calculations. + float external_page_scale_factor = + layer_tree_impl() ? layer_tree_impl()->external_page_scale_factor() + : 1.f; + DCHECK(!layer_tree_impl() || external_page_scale_factor == 1.f || + layer_tree_impl()->current_page_scale_factor() == 1.f); + ideal_page_scale_ = external_page_scale_factor; + ideal_contents_scale_ = + GetIdealContentsScale() * external_page_scale_factor; + } ideal_contents_scale_ = std::min(kMaxIdealContentsScale, - std::max(GetIdealContentsScale(), min_contents_scale)); + std::max(ideal_contents_scale_, min_contents_scale)); ideal_source_scale_ = ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_; }
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc index edaef8e..db05b11 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -161,7 +161,8 @@ } void AsyncLayerTreeFrameSink::SubmitCompositorFrame( - viz::CompositorFrame frame) { + viz::CompositorFrame frame, + bool show_hit_test_borders) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(compositor_frame_sink_ptr_); DCHECK(frame.metadata.begin_frame_ack.has_damage); @@ -205,6 +206,9 @@ else hit_test_region_list = client_->BuildHitTestData(); + // TODO(zandershah): Add kHitTestDebug flag to |hit_test_region_list_| if + // |show_hit_test_borders| is set. https://crbug.com/895600 + if (last_submitted_local_surface_id_ != local_surface_id_) { last_submitted_local_surface_id_ = local_surface_id_; last_submitted_device_scale_factor_ = frame.device_scale_factor();
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.h b/cc/mojo_embedder/async_layer_tree_frame_sink.h index 339ec47..3eea4d96 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.h +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.h
@@ -117,7 +117,8 @@ bool BindToClient(LayerTreeFrameSinkClient* client) override; void DetachFromClient() override; void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id) override; - void SubmitCompositorFrame(viz::CompositorFrame frame) override; + void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) override;
diff --git a/cc/test/fake_layer_tree_frame_sink.cc b/cc/test/fake_layer_tree_frame_sink.cc index 03b4e25..d739e87 100644 --- a/cc/test/fake_layer_tree_frame_sink.cc +++ b/cc/test/fake_layer_tree_frame_sink.cc
@@ -60,7 +60,9 @@ LayerTreeFrameSink::DetachFromClient(); } -void FakeLayerTreeFrameSink::SubmitCompositorFrame(viz::CompositorFrame frame) { +void FakeLayerTreeFrameSink::SubmitCompositorFrame( + viz::CompositorFrame frame, + bool submit_hit_test_borders) { ReturnResourcesHeldByParent(); last_sent_frame_ = std::make_unique<viz::CompositorFrame>(std::move(frame));
diff --git a/cc/test/fake_layer_tree_frame_sink.h b/cc/test/fake_layer_tree_frame_sink.h index 5b15660..38f25f8 100644 --- a/cc/test/fake_layer_tree_frame_sink.h +++ b/cc/test/fake_layer_tree_frame_sink.h
@@ -100,7 +100,8 @@ // LayerTreeFrameSink implementation. bool BindToClient(LayerTreeFrameSinkClient* client) override; void DetachFromClient() override; - void SubmitCompositorFrame(viz::CompositorFrame frame) override; + void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) override;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 5286c21..d94c3b6 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -87,9 +87,11 @@ frame_request_pending_ = true; InvalidateIfPossible(); } - void SubmitCompositorFrame(viz::CompositorFrame frame) override { + void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) override { frame_ack_pending_ = true; - viz::TestLayerTreeFrameSink::SubmitCompositorFrame(std::move(frame)); + viz::TestLayerTreeFrameSink::SubmitCompositorFrame(std::move(frame), + show_hit_test_borders); } void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override {
diff --git a/cc/trees/layer_tree_frame_sink.h b/cc/trees/layer_tree_frame_sink.h index f84efe0..15b3568 100644 --- a/cc/trees/layer_tree_frame_sink.h +++ b/cc/trees/layer_tree_frame_sink.h
@@ -105,8 +105,11 @@ // For successful swaps, the implementation must call // DidReceiveCompositorFrameAck() asynchronously when the frame has been - // processed in order to unthrottle the next frame. - virtual void SubmitCompositorFrame(viz::CompositorFrame frame) = 0; + // processed in order to unthrottle the next frame. |show_hit_test_borders| + // controls whether viz will insert debug borders over hit-test data and is + // passed from LayerTreeDebugState. + virtual void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) = 0; // Signals that a BeginFrame issued by the viz::BeginFrameSource provided to // the client did not lead to a CompositorFrame submission.
diff --git a/cc/trees/layer_tree_frame_sink_unittest.cc b/cc/trees/layer_tree_frame_sink_unittest.cc index 355b818c..cd40a54 100644 --- a/cc/trees/layer_tree_frame_sink_unittest.cc +++ b/cc/trees/layer_tree_frame_sink_unittest.cc
@@ -28,7 +28,8 @@ std::move(compositor_task_runner), nullptr) {} - void SubmitCompositorFrame(viz::CompositorFrame frame) override { + void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) override { client_->DidReceiveCompositorFrameAck(); } void DidNotProduceFrame(const viz::BeginFrameAck& ack) override {}
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 26f0833f..3ccc554f 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -180,8 +180,8 @@ LayerTreeHost::~LayerTreeHost() { // Track when we're inside a main frame to see if compositor is being - // destroyed midway which causes a crash. crbug.com/654672 - DCHECK(!inside_main_frame_); + // destroyed midway which causes a crash. crbug.com/895883 + CHECK(!inside_main_frame_); TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost"); // Clear any references into the LayerTreeHost. @@ -1255,6 +1255,14 @@ this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } +void LayerTreeHost::SetExternalPageScaleFactor(float page_scale_factor) { + if (external_page_scale_factor_ == page_scale_factor) + return; + + external_page_scale_factor_ = page_scale_factor; + SetNeedsCommit(); +} + void LayerTreeHost::SetContentSourceId(uint32_t id) { content_source_id_ = id; } @@ -1486,6 +1494,7 @@ tree_impl->elastic_overscroll()->PushPendingToActive(); tree_impl->SetRasterColorSpace(raster_color_space_id_, raster_color_space_); + tree_impl->SetExternalPageScaleFactor(external_page_scale_factor_); tree_impl->set_content_source_id(content_source_id_);
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 63cd5e7..7be47d9 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -435,6 +435,13 @@ return raster_color_space_; } + // This layer tree may be embedded in a hierarchy that has page scale + // factor controlled at the top level. We represent that scale here as + // 'external_page_scale_factor', a value that affects raster scale in the + // same way that page_scale_factor does, but doesn't affect any geometry + // calculations. + void SetExternalPageScaleFactor(float page_scale_factor); + // Used externally by blink for setting the PropertyTrees when // UseLayerLists() is true, which also implies that Slimming Paint // v2 is enabled. @@ -725,6 +732,7 @@ float page_scale_factor_ = 1.f; float min_page_scale_factor_ = 1.f; float max_page_scale_factor_ = 1.f; + float external_page_scale_factor_ = 1.f; int raster_color_space_id_ = -1; gfx::ColorSpace raster_color_space_;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 5d85061..49f342a4 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2004,6 +2004,8 @@ metadata.viewport_size_in_pixels = active_tree_->GetDeviceViewport().size(); metadata.page_scale_factor = active_tree_->current_page_scale_factor(); + metadata.external_page_scale_factor = + active_tree_->external_page_scale_factor(); metadata.top_controls_height = browser_controls_offset_manager_->TopControlsHeight(); @@ -2080,7 +2082,8 @@ } auto compositor_frame = GenerateCompositorFrame(frame); - layer_tree_frame_sink_->SubmitCompositorFrame(std::move(compositor_frame)); + layer_tree_frame_sink_->SubmitCompositorFrame( + std::move(compositor_frame), debug_state_.show_hit_test_borders); // Clears the list of swap promises after calling DidSwap on each of them to // signal that the swap is over.
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index e14b18d..370373629 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -85,6 +85,7 @@ page_scale_factor_(page_scale_factor), min_page_scale_factor_(0), max_page_scale_factor_(0), + external_page_scale_factor_(1.f), device_scale_factor_(1.f), painted_device_scale_factor_(1.f), content_source_id_(0), @@ -476,6 +477,7 @@ // tree so only the limits need to be provided. target_tree->PushPageScaleFactorAndLimits(nullptr, min_page_scale_factor(), max_page_scale_factor()); + target_tree->SetExternalPageScaleFactor(external_page_scale_factor_); target_tree->SetRasterColorSpace(raster_color_space_id_, raster_color_space_); target_tree->elastic_overscroll()->PushPendingToActive(); @@ -1104,6 +1106,15 @@ raster_color_space_ = raster_color_space; } +void LayerTreeImpl::SetExternalPageScaleFactor( + float external_page_scale_factor) { + if (external_page_scale_factor_ == external_page_scale_factor) + return; + + external_page_scale_factor_ = external_page_scale_factor; + DidUpdatePageScale(); +} + SyncedProperty<ScaleGroup>* LayerTreeImpl::page_scale_factor() { return page_scale_factor_.get(); }
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 64e445c..e858749e 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -351,6 +351,10 @@ void SetRasterColorSpace(int raster_color_space_id, const gfx::ColorSpace& raster_color_space); + void SetExternalPageScaleFactor(float external_page_scale_factor); + float external_page_scale_factor() const { + return external_page_scale_factor_; + } const gfx::ColorSpace& raster_color_space() const { return raster_color_space_; } @@ -645,6 +649,7 @@ scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor_; float min_page_scale_factor_; float max_page_scale_factor_; + float external_page_scale_factor_; float device_scale_factor_; float painted_device_scale_factor_;
diff --git a/cc/trees/render_frame_metadata.cc b/cc/trees/render_frame_metadata.cc index 304b451..975bd9c 100644 --- a/cc/trees/render_frame_metadata.cc +++ b/cc/trees/render_frame_metadata.cc
@@ -32,6 +32,7 @@ device_scale_factor == other.device_scale_factor && viewport_size_in_pixels == other.viewport_size_in_pixels && page_scale_factor == other.page_scale_factor && + external_page_scale_factor == other.external_page_scale_factor && top_controls_height == other.top_controls_height && top_controls_shown_ratio == other.top_controls_shown_ratio && #if defined(OS_ANDROID)
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h index 0ad5b4f..13c13349 100644 --- a/cc/trees/render_frame_metadata.h +++ b/cc/trees/render_frame_metadata.h
@@ -68,7 +68,10 @@ // The time at which |local_surface_id| was allocated. base::Optional<base::TimeTicks> local_surface_id_allocation_time_from_child; + // Page scale factor (always 1.f for sub-frame renderers). float page_scale_factor = 1.f; + // Used for testing propagation of page scale factor to sub-frame renderers. + float external_page_scale_factor = 1.f; // Used to position the location top bar and page content, whose precise // position is computed by the renderer compositor.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 4b60609..cf0e640 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -309,6 +309,7 @@ "//net/android:net_java", "//printing:printing_java", "//services/data_decoder/public/cpp/android:safe_json_java", + "//services/media_session/public/cpp/android:media_session_java", "//services/network/public/mojom:mojom_java", "//services/service_manager/public/java:service_manager_java", "//services/service_manager/public/mojom:mojom_java", @@ -559,6 +560,7 @@ "//mojo/public/java:bindings_java", "//mojo/public/java:system_java", "//net/android:net_java", + "//services/media_session/public/cpp/android:media_session_java", "//third_party/android_deps:android_arch_lifecycle_common_java", "//third_party/android_deps:android_support_annotations_java", "//third_party/android_deps:android_support_v7_appcompat_java",
diff --git a/chrome/android/DEPS b/chrome/android/DEPS index a234ece..52b14e0 100644 --- a/chrome/android/DEPS +++ b/chrome/android/DEPS
@@ -7,4 +7,5 @@ "+components/spellcheck/browser", "+jni", "+media/base/android/java", + "+services/media_session/public", ]
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 7d7cbb2..4692a934 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -111,6 +111,8 @@ # Use zh-TW strings for zh-HK (https://crbug.com/780847). support_zh_hk = true + optimize_resources = true + if (defined(shared_libraries) && shared_libraries != []) { _native_lib_file = rebase_path("$root_gen_dir/CHROME_VERSION.json", root_out_dir) @@ -231,6 +233,9 @@ # Webview supports all locales (has no omitted ones). aapt_locale_whitelist = locales + # Resources config for blocklisting resource names from obfuscation + resources_config_path = "//android_webview/aapt2.config" + if (!defined(invoker.target_type) || invoker.target_type == "android_apk") { # Incremental install doesn't work for monochrome. See crbug.com/663492. never_incremental = true
diff --git a/chrome/android/java/res/color/checkbox_tint.xml b/chrome/android/java/res/color/checkbox_tint.xml index cc10e11..e21a830 100644 --- a/chrome/android/java/res/color/checkbox_tint.xml +++ b/chrome/android/java/res/color/checkbox_tint.xml
@@ -5,5 +5,5 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:color="@color/light_active_color" /> - <item android:color="@color/light_normal_color"/> + <item android:color="@color/control_normal_color"/> </selector>
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml index 7b61225..6a79adb 100644 --- a/chrome/android/java/res/values-v17/styles.xml +++ b/chrome/android/java/res/values-v17/styles.xml
@@ -27,9 +27,9 @@ <item name="android:statusBarColor" tools:targetApi="21">@android:color/black</item> <!-- Overriding AppCompat values --> - <!-- TODO(huayinz): Change this when the color for checkboxes are updated to modern. --> - <item name="colorControlNormal">@color/light_normal_color</item> + <item name="colorControlNormal">@color/control_normal_color</item> <item name="colorControlActivated">@color/light_active_color</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> <!-- Navigation Transitions, requires API level 21 --> <item name="android:windowAllowEnterTransitionOverlap" tools:targetApi="21">false</item> @@ -70,6 +70,7 @@ <item name="colorPrimaryDark">@android:color/black</item> <item name="colorPrimary">@color/light_active_color</item> <item name="colorAccent">@color/light_active_color</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="windowNoTitle">true</item> </style> <style name="FullscreenWhite" parent="FullscreenWhiteBase" /> @@ -80,6 +81,7 @@ <item name="android:windowIsFloating">true</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowIsTranslucent">true</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="windowNoTitle">true</item> </style> @@ -103,7 +105,8 @@ <!-- Overriding AppCompat values --> <item name="colorAccent">@color/light_active_color</item> <item name="colorControlActivated">@color/light_active_color</item> - <item name="colorControlNormal">@color/light_normal_color</item> + <item name="colorControlNormal">@color/control_normal_color</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="colorPrimary">@color/light_active_color</item> </style> @@ -220,6 +223,7 @@ <item name="colorPrimaryDark">@android:color/black</item> <!-- Color of checkboxes, switches, buttons, etc. --> <item name="colorAccent">@color/pref_accent_color</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> </style> <style name="ThemeWithActionBar" parent="ThemeWithActionBarBase" /> @@ -277,6 +281,7 @@ <item name="android:listDivider">@null</item> <item name="android:listPreferredItemHeightSmall">48dp</item> <item name="android:textAppearance">@style/BlackTitle1</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> </style> <style name="OverflowMenuButton"> <item name="android:layout_width">0dp</item> @@ -452,6 +457,7 @@ <item name="android:textColorLink">@color/default_text_color_link</item> <item name="colorPrimaryDark">@android:color/black</item> <item name="colorAccent">@color/light_active_color</item> + <item name="colorControlHighlight">@color/control_highlight_color</item> <!-- Remove ActionBar --> <item name="windowNoTitle">true</item>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index f8269113c..049d6ff 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -13,10 +13,11 @@ <color name="text_highlight_color">#C6DAFC</color> <color name="error_text_color">@color/google_red_700</color> - <!-- Control colors for toggles, checkboxes, ratio buttons and accent. --> - <!-- Deprecated. Use dark_mode_tint or default_icon_color for icons instead. --> - <color name="light_normal_color">#5A5A5A</color> + <!-- Control colors for toggles, checkboxes, ratio buttons, list item highlight, and accent. + Note that these should NOT be used for icon tint. --> + <color name="control_normal_color">@color/modern_grey_700</color> <color name="light_active_color">@color/modern_blue_600</color> + <color name="control_highlight_color">@color/modern_grey_800_alpha_38</color> <!-- Icon colors for drawables. --> <color name="light_icon_color">@color/modern_grey_500</color> @@ -38,6 +39,8 @@ <color name="white_alpha_65">#A6FFFFFF</color> <color name="white_alpha_90">#E6FFFFFF</color> + <color name="modern_grey_800_alpha_38">#613C4043</color> + <!-- Old color palette --> <color name="google_blue_grey_500">#607D8B</color> <color name="google_blue_50">#E3F2FD</color>
diff --git a/chrome/android/java/res_download/layout/download_home_toolbar.xml b/chrome/android/java/res_download/layout/download_home_toolbar.xml index d764c6c..18f3e73c 100644 --- a/chrome/android/java/res_download/layout/download_home_toolbar.xml +++ b/chrome/android/java/res_download/layout/download_home_toolbar.xml
@@ -8,7 +8,7 @@ android:layout_height="wrap_content"> <org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar - android:id="@+id/toolbar" + android:id="@+id/download_toolbar" android:layout_width="match_parent" android:layout_height="@dimen/toolbar_height_no_shadow" style="@style/ModernToolbar">
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java index 40e701b..b7932b86 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialog.java
@@ -131,7 +131,7 @@ */ @Nullable String getFileName() { - if (mFileName == null) return null; + if (mFileName == null || mFileName.getText() == null) return null; return mFileName.getText().toString(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java index c0cc0a06..77475f7a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java
@@ -138,7 +138,7 @@ private void handleResponses( String fileName, DirectoryOption directoryOption, boolean dontShowAgain) { // If there's no file location, treat as a cancellation. - if (directoryOption == null || directoryOption.location == null) { + if (directoryOption == null || directoryOption.location == null || fileName == null) { cancel(); return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java index 69ac992..b8543b05 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java
@@ -108,7 +108,7 @@ mView = (ViewGroup) LayoutInflater.from(context).inflate( R.layout.download_home_toolbar, null); - mToolbar = mView.findViewById(R.id.toolbar); + mToolbar = mView.findViewById(R.id.download_toolbar); mShadow = mView.findViewById(R.id.shadow); mToolbar.initialize(selectionDelegate, 0 /* titleResId */, null /* drawerLayout */,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java index c1c564f..f995b00 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
@@ -50,10 +50,12 @@ } /** - * Removes the close button from the toolbar. + * Removes a menu item from the toolbar. + * @param menuItemId The menu item to be removed. Nothing happens if there is no menu item + * associated with this ID. */ - public void removeCloseButton() { - getMenu().removeItem(R.id.close_menu_id); + public void removeMenuItem(int menuItemId) { + getMenu().removeItem(menuItemId); } /** Called whenever the selected filter on this adapter should change. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java index c2084fd..88f7c30c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -231,6 +231,8 @@ isLocationEnabled ? R.id.with_settings_normal_menu_group : R.id.normal_menu_group; mSearchMenuId = isLocationEnabled ? R.id.with_settings_search_menu_id : R.id.search_menu_id; mInfoMenuId = isLocationEnabled ? 0 : R.id.info_menu_id; + final int closeMenuId = + isLocationEnabled ? R.id.with_settings_close_menu_id : R.id.close_menu_id; mToolbar = (DownloadManagerToolbar) mSelectableListLayout.initializeToolbar( R.layout.download_manager_toolbar, mBackendProvider.getSelectionDelegate(), 0, null, @@ -253,7 +255,7 @@ enableStorageInfoHeader(mHistoryAdapter.shouldShowStorageInfoHeader()); mIsSeparateActivity = isSeparateActivity; - if (!mIsSeparateActivity) mToolbar.removeCloseButton(); + if (!mIsSeparateActivity) mToolbar.removeMenuItem(closeMenuId); RecordUserAction.record("Android.DownloadManager.Open"); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java index 3b091fc..19943aa 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/CastNotificationControl.java
@@ -23,7 +23,7 @@ import org.chromium.chrome.browser.metrics.MediaNotificationUma; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.url_formatter.UrlFormatter; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.net.URI; import java.net.URISyntaxException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java index 78dfaf1..7f6fa0c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java
@@ -8,7 +8,7 @@ import com.google.android.gms.cast.RemoteMediaPlayer; import org.chromium.chrome.browser.media.ui.MediaNotificationInfo; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; /** * Helper class that implements functions useful to all CastSession types.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java index 19340e2..878ca06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java
@@ -16,7 +16,7 @@ import org.chromium.chrome.browser.media.ui.MediaNotificationManager; import org.chromium.chrome.browser.metrics.MediaNotificationUma; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; /** Controller for updating media notification for Casting and MediaFling. */ public class CafNotificationController implements MediaNotificationListener {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java index 74ab781..3019531 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.browser.media.ui; -import static org.chromium.content_public.common.MediaMetadata.MediaImage; +import static org.chromium.services.media_session.MediaMetadata.MediaImage; import android.graphics.Bitmap; import android.graphics.Rect;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationInfo.java index 179f43a..2282eba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationInfo.java
@@ -9,7 +9,7 @@ import android.text.TextUtils; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.HashSet; import java.util.Set;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java index 4305081e..485c3352 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java
@@ -48,7 +48,7 @@ import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.ArrayList; import java.util.HashSet;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java index aaa71f4..bb8d6f77 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
@@ -28,7 +28,7 @@ import org.chromium.content_public.browser.MediaSession; import org.chromium.content_public.browser.MediaSessionObserver; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import org.chromium.ui.base.WindowAndroid; import java.net.URI;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java index 7246c90..2181add2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
@@ -66,7 +66,7 @@ private int mAppMinArCoreApkVersionCode = ARCORE_NOT_INSTALLED_VERSION_CODE; @UsedByReflection("ArDelegate.java") - /* package */ static void installArCoreDeviceProviderFactory() { + public static void installArCoreDeviceProviderFactory() { nativeInstallArCoreDeviceProviderFactory(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArDelegate.java index 55db849..227cd1e5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArDelegate.java
@@ -18,9 +18,16 @@ Class.forName("org.chromium.chrome.browser.vr.ArCoreJavaUtils") .getDeclaredMethod("installArCoreDeviceProviderFactory") .invoke(null); - } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException - | NoSuchMethodException | InvocationTargetException e) { + } catch (ClassNotFoundException e) { // AR not available. No initialization required. + } catch (NoSuchMethodException e) { + // This and the exceptions below should not happen. Multiple catch statements to work + // around ReflectiveOperationException in API level 19. + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java index fc6eac0d..f378aee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java
@@ -136,6 +136,23 @@ private ArrayList<Integer> mUiOperationResults; private ArrayList<Runnable> mUiOperationResultCallbacks; + /** + * A struct-like object for registering UI operations during tests. + */ + @VisibleForTesting + public static class UiOperationData { + // The UiTestOperationType of this operation. + public int actionType; + // The callback to run when the operation completes. + public Runnable resultCallback; + // The timeout of the operation. + public int timeoutMs; + // The UserFriendlyElementName to perform the operation on. + public int elementName; + // The desired visibility status of the element. + public boolean visibility; + } + public VrShell( ChromeActivity activity, VrShellDelegate delegate, TabModelSelector tabModelSelector) { super(activity); @@ -1233,8 +1250,8 @@ }); } - public void registerUiOperationCallbackForTesting( - int actionType, Runnable resultCallback, int timeoutMs, int elementName) { + public void registerUiOperationCallbackForTesting(UiOperationData operationData) { + int actionType = operationData.actionType; assert actionType < UiTestOperationType.NUM_UI_TEST_OPERATION_TYPES; // Fill the ArrayLists if this is the first time the method has been called. if (mUiOperationResults == null) { @@ -1248,14 +1265,15 @@ } } mUiOperationResults.set(actionType, UiTestOperationResult.UNREPORTED); - mUiOperationResultCallbacks.set(actionType, resultCallback); + mUiOperationResultCallbacks.set(actionType, operationData.resultCallback); // In the case of the UI activity quiescence callback type, we need to let the native UI // know how long to wait before timing out. if (actionType == UiTestOperationType.UI_ACTIVITY_RESULT) { - nativeSetUiExpectingActivityForTesting(mNativeVrShell, timeoutMs); - } else if (actionType == UiTestOperationType.ELEMENT_VISIBILITY_CHANGE) { - nativeWatchElementForVisibilityChangeForTesting(mNativeVrShell, elementName, timeoutMs); + nativeSetUiExpectingActivityForTesting(mNativeVrShell, operationData.timeoutMs); + } else if (actionType == UiTestOperationType.ELEMENT_VISIBILITY_STATUS) { + nativeWatchElementForVisibilityStatusForTesting(mNativeVrShell, + operationData.elementName, operationData.timeoutMs, operationData.visibility); } } @@ -1327,8 +1345,8 @@ long nativeVrShell, int quiescenceTimeoutMs); private native void nativeSaveNextFrameBufferToDiskForTesting( long nativeVrShell, String filepathBase); - private native void nativeWatchElementForVisibilityChangeForTesting( - long nativeVrShell, int elementName, int timeoutMs); + private native void nativeWatchElementForVisibilityStatusForTesting( + long nativeVrShell, int elementName, int timeoutMs, boolean visibility); private native void nativeResumeContentRendering(long nativeVrShell); private native void nativeOnOverlayTextureEmptyChanged(long nativeVrShell, boolean empty); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index 8ab40e18..826798b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -1844,7 +1844,9 @@ Assert.assertTrue("notifyChanged() was not called", mNotifyChangedCalled); } + // Flaky: http://crbug.com/901986 @Test + @DisabledTest @MediumTest @Feature({"Android-TabSwitcher"}) @RetryOnFailure
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java index ad619f8..1059297 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/EmulatedVrController.java
@@ -78,7 +78,7 @@ } /** - * Either presses or releases the Daydream controller's touchpad button depending on wheter + * Either presses or releases the Daydream controller's touchpad button depending on whether * the button is currently pressed or not. */ public void sendClickButtonToggleEvent() { @@ -94,6 +94,14 @@ } /** + * Either presses or releases the Daydream controller's app button depending on whether the + * button is currently pressed or not. + */ + public void sendAppButtonToggleEvent() { + getApi().buttonEvent.sendAppButtonToggleEvent(); + } + + /** * Presses and quickly releases the Daydream controller's app button. * Or, if the button is already pressed, releases and quickly presses again. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java index 62398178..e3571d54 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/TestVrShellDelegate.java
@@ -98,10 +98,8 @@ getVrShell().performKeyboardInputForTesting(inputType, inputString); } - public void registerUiOperationCallbackForTesting( - int actionType, Runnable resultCallback, int timeoutMs, int elementName) { - getVrShell().registerUiOperationCallbackForTesting( - actionType, resultCallback, timeoutMs, elementName); + public void registerUiOperationCallbackForTesting(VrShell.UiOperationData operationData) { + getVrShell().registerUiOperationCallbackForTesting(operationData); } public void saveNextFrameBufferToDiskForTesting(String filepathBase) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java index fdc5612a..50dc49f7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
@@ -409,7 +409,7 @@ NativeUiUtils.revertToRealInput(); // Wait for the URL bar to re-appear, which we take as a signal that we've exited omnibox // text input mode. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.URL, () -> { mController.pressReleaseAppButton(); }); + NativeUiUtils.performActionAndWaitForVisibilityStatus(UserFriendlyElementName.URL, + true /* visible */, () -> { mController.pressReleaseAppButton(); }); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNativeUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNativeUiTest.java index 7e715e62..0eec91dd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNativeUiTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNativeUiTest.java
@@ -152,8 +152,8 @@ NativeUiUtils.inputBackspace(); } // Wait for suggestions to change so that our navigation succeeds. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("version/"); }); NativeUiUtils.inputEnter(); ChromeTabUtils.waitForTabPageLoaded( @@ -181,8 +181,9 @@ UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF(-0.45f, 0.0f)); // We expect this to delete an "a" instead of anything in "chrome://". Do so and wait for // the suggestions to appear. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, () -> { NativeUiUtils.inputBackspace(); }); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, + () -> { NativeUiUtils.inputBackspace(); }); NativeUiUtils.inputEnter(); // Navigating automatically appends a "/". ChromeTabUtils.waitForTabPageLoaded( @@ -201,8 +202,8 @@ NativeUiUtils.enableMockedKeyboard(); NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); // Input text and close the omnibox without committing. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://version/"); }); NativeUiUtils.clickElementAndWaitForUiQuiescence( UserFriendlyElementName.OMNIBOX_CLOSE_BUTTON, new PointF()); @@ -215,8 +216,8 @@ for (int i = 0; i < 11; ++i) { NativeUiUtils.inputBackspace(); } - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visibile */, () -> { NativeUiUtils.inputString("chrome://version/"); }); NativeUiUtils.inputEnter(); // This should only succeed if the original "chrome://version/" we input is not present - @@ -241,8 +242,8 @@ // Test that autocompletion works with only one option left. NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); // This should autocomplete to "chrome://version". - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://v"); }); NativeUiUtils.inputEnter(); ChromeTabUtils.waitForTabPageLoaded( @@ -252,8 +253,8 @@ // Test that autocompletion updates successfully when entering more text. NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://v"); }); NativeUiUtils.inputString("e"); // Since suggestions are already visible, we need to wait for suggestions to update via @@ -267,8 +268,8 @@ NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); // This could be either "chrome://net-export" or "chrome://net-internals", so it shouldn't // autocomplete to anything. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://net-"); }); NativeUiUtils.inputEnter(); ChromeTabUtils.waitForTabPageLoaded( @@ -277,8 +278,8 @@ // Test that autocompletion cancels if a non-matching character is input. NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); // This should autocomplete to "chrome://version". - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://v"); }); NativeUiUtils.inputString("a"); NativeUiUtils.waitNumFrames(NativeUiUtils.NUM_FRAMES_FOR_SUGGESTION_UPDATE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java index 63f6672c..d1e8d4a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
@@ -693,8 +693,8 @@ // having suggestions present, waiting for a number of frames before committing seemed // stable. Adding an operation to listen for suggestion changes would also work, but // would add some pretty niche test-only code to the native side. - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://version/"); }); NativeUiUtils.inputEnter(); ChromeTabUtils.waitForTabPageLoaded( @@ -728,8 +728,8 @@ private void testSuggestionClickTriggersNavigationImpl() throws InterruptedException { NativeUiUtils.enableMockedKeyboard(); NativeUiUtils.clickElementAndWaitForUiQuiescence(UserFriendlyElementName.URL, new PointF()); - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.SUGGESTION_BOX, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.SUGGESTION_BOX, true /* visible */, () -> { NativeUiUtils.inputString("chrome://"); }); // Blindly clicking in the center of the suggestion box should end up clicking the middle // suggestion, which for "chrome://" should be a valid chrome:// URL.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java index 3cd7df9..bfddcf3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrInstallUpdateInfoBarTest.java
@@ -186,8 +186,8 @@ // prompt to become visible before waiting for quiescence. NativeUiUtils.performActionAndWaitForUiQuiescence(() -> { try { - NativeUiUtils.performActionAndWaitForVisibilityChange( - UserFriendlyElementName.EXIT_PROMPT, + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.EXIT_PROMPT, true /* visible */, () -> { NativeUiUtils.clickElement(uiElementToClick, new PointF()); }); } catch (InterruptedException e) { Assert.fail("Interrupted while waiting for UI visibility change");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java index e2bde6a..2f7a566a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -12,8 +12,10 @@ import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE; import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_NON_DAYDREAM; +import android.graphics.PointF; import android.os.Build; import android.os.SystemClock; +import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.filters.MediumTest; import android.view.MotionEvent; @@ -37,8 +39,11 @@ import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; import org.chromium.chrome.browser.vr.mock.MockVrDaydreamApi; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction; +import org.chromium.chrome.browser.vr.util.NativeUiUtils; +import org.chromium.chrome.browser.vr.util.PermissionUtils; import org.chromium.chrome.browser.vr.util.VrShellDelegateUtils; import org.chromium.chrome.browser.vr.util.VrTestRuleUtils; import org.chromium.chrome.browser.vr.util.VrTransitionUtils; @@ -47,6 +52,7 @@ import org.chromium.content_public.browser.ViewEventSink; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TouchCommon; +import org.chromium.net.test.EmbeddedTestServer; import java.util.List; import java.util.concurrent.Callable; @@ -696,4 +702,171 @@ + String.valueOf(numExpectedGamepads) + ")"); mWebXrVrTestFramework.endTest(); } + + /** + * Tests that long pressing the app button shows a toast indicating which permissions are in + * use, and that it disappears at the correct time. + */ + @Test + @LargeTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL}) + public void testAppButtonLongPressDisplaysPermissions() throws InterruptedException { + testAppButtonLongPressDisplaysPermissionsImpl(); + } + + /** + * Tests that long pressing the app button shows a toast indicating which permissions are in + * use, and that it disappears at the correct time while in incognito mode. + */ + @Test + @LargeTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA}) + public void testAppButtonLongPressDisplaysPermissionsIncognito() + throws InterruptedException { + ThreadUtils.runOnUiThreadBlocking(() -> { + mTestRule.getActivity() + .getTabCreator(true /* incognito */) + .launchUrl("about:blank", TabLaunchType.FROM_LINK); + }); + testAppButtonLongPressDisplaysPermissionsImpl(); + } + + private void testAppButtonLongPressDisplaysPermissionsImpl() throws InterruptedException { + // Note that we need to pass in the WebContents to use throughout this because automatically + // using the first tab's WebContents doesn't work in Incognito. + EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); + EmbeddedTestServer server = mTestRule.getTestServer(); + boolean teardownServer = false; + if (server == null) { + server = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + teardownServer = true; + } + mWebXrVrTestFramework.loadUrlAndAwaitInitialization( + server.getURL(WebXrVrTestFramework.getEmbeddedServerPathForHtmlTestFile( + "generic_webxr_permission_page")), + PAGE_LOAD_TIMEOUT_S); + WebXrVrTestFramework.runJavaScriptOrFail("requestPermission({audio:true})", + POLL_TIMEOUT_SHORT_MS, mTestRule.getWebContents()); + PermissionUtils.waitForPermissionPrompt(); + PermissionUtils.acceptPermissionPrompt(); + WebXrVrTestFramework.waitOnJavaScriptStep(mTestRule.getWebContents()); + mWebXrVrTestFramework.enterSessionWithUserGestureOrFail(mTestRule.getWebContents()); + // The permission toasts automatically show for ~5 seconds when entering an immersive + // session, so wait for that to disappear + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {}); + SystemClock.sleep(4500); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, false /* visible */, () -> {}); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, + () -> { controller.sendAppButtonToggleEvent(); }); + // The toast should automatically disappear after ~5 second after the button is pressed, + // regardless of whether it's released or not. + SystemClock.sleep(1000); + controller.sendAppButtonToggleEvent(); + SystemClock.sleep(3500); + // Make sure it's still present shortly before we expect it to disappear. + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {}); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, false /* visible */, () -> {}); + // Do the same, but make sure the toast disappears even with the button still held. + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, + () -> { controller.sendAppButtonToggleEvent(); }); + SystemClock.sleep(4500); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {}); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, false /* visible */, () -> {}); + if (teardownServer) { + server.stopAndDestroyServer(); + } + } + + /** + * Tests that permission requests while in a WebXR for VR exclusive session work as expected. + */ + @Test + @MediumTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + // TODO(https://crbug.com/901494): Make this run everywhere when permissions are + // unbroken. + @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA}) + public void testInSessionPermissionRequests() throws InterruptedException { + testInSessionPermissionRequestsImpl(); + } + + @Test + @MediumTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA}) + public void testInSessionPermissionRequestsIncognito() throws InterruptedException { + ThreadUtils.runOnUiThreadBlocking(() -> { + mTestRule.getActivity() + .getTabCreator(true /* incognito */) + .launchUrl("about:blank", TabLaunchType.FROM_LINK); + }); + testInSessionPermissionRequestsImpl(); + } + + private void testInSessionPermissionRequestsImpl() throws InterruptedException { + // Note that we need to pass in the WebContents to use throughout this because automatically + // using the first tab's WebContents doesn't work in Incognito. + EmbeddedTestServer server = mTestRule.getTestServer(); + boolean teardownServer = false; + if (server == null) { + server = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + teardownServer = true; + } + + mWebXrVrTestFramework.loadUrlAndAwaitInitialization( + server.getURL(WebXrVrTestFramework.getEmbeddedServerPathForHtmlTestFile( + "generic_webxr_permission_page")), + PAGE_LOAD_TIMEOUT_S); + mWebXrVrTestFramework.enterSessionWithUserGestureOrFail(mTestRule.getWebContents()); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_HOSTED_CONTENT, true /* visible */, () -> { + WebXrVrTestFramework.runJavaScriptOrFail("requestPermission({audio:true})", + POLL_TIMEOUT_SHORT_MS, mTestRule.getWebContents()); + }); + // Click outside the prompt and ensure that it gets dismissed. + NativeUiUtils.clickElement( + UserFriendlyElementName.WEB_XR_HOSTED_CONTENT, new PointF(0.55f, 0.0f)); + WebXrVrTestFramework.waitOnJavaScriptStep(mTestRule.getWebContents()); + + // Accept the permission this time and ensure it propogates to the page. + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_HOSTED_CONTENT, true /* visible */, () -> { + WebXrVrTestFramework.runJavaScriptOrFail("requestPermission({audio:true})", + POLL_TIMEOUT_SHORT_MS, mTestRule.getWebContents()); + }); + NativeUiUtils.clickElement( + UserFriendlyElementName.WEB_XR_HOSTED_CONTENT, new PointF(0.4f, -0.4f)); + WebXrVrTestFramework.waitOnJavaScriptStep(mTestRule.getWebContents()); + Assert.assertTrue("Could not grant permission while in WebXR immersive session", + WebXrVrTestFramework + .runJavaScriptOrFail("lastPermissionRequestSucceeded", + POLL_TIMEOUT_SHORT_MS, mTestRule.getWebContents()) + .equals("true")); + + if (teardownServer) { + server.stopAndDestroyServer(); + } + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTabTest.java index cb79cff..620b418 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTabTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTabTest.java
@@ -5,8 +5,11 @@ package org.chromium.chrome.browser.vr; import static org.chromium.chrome.browser.vr.XrTestFramework.PAGE_LOAD_TIMEOUT_S; +import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_SHORT_MS; +import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE; import android.os.Build; +import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import org.junit.Before; @@ -15,16 +18,22 @@ import org.junit.rules.RuleChain; import org.junit.runner.RunWith; +import org.chromium.base.ThreadUtils; import org.chromium.base.test.params.ParameterAnnotations.ClassParameter; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; +import org.chromium.chrome.browser.vr.util.NativeUiUtils; +import org.chromium.chrome.browser.vr.util.PermissionUtils; import org.chromium.chrome.browser.vr.util.VrTestRuleUtils; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.net.test.EmbeddedTestServer; import java.util.List; import java.util.concurrent.Callable; @@ -93,4 +102,72 @@ framework.executeStepAndWait("stepCheckFrameDataWhileNonFocusedTab()"); framework.endTest(); } + + /** + * Tests that permissions in use by other tabs are shown while in a WebXR for VR immersive + * session. + */ + @Test + @MediumTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + public void testPermissionsInOtherTab() throws InterruptedException { + testPermissionsInOtherTabImpl(false /* incognito */); + } + + @Test + @MediumTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + public void testPermissionsInOtherTabIncognito() throws InterruptedException { + testPermissionsInOtherTabImpl(true /* incognito */); + } + + private void testPermissionsInOtherTabImpl(boolean incognito) throws InterruptedException { + EmbeddedTestServer server = mTestRule.getTestServer(); + boolean teardownServer = false; + if (server == null) { + server = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + teardownServer = true; + } + + mWebXrVrTestFramework.loadUrlAndAwaitInitialization( + server.getURL(WebXrVrTestFramework.getEmbeddedServerPathForHtmlTestFile( + "generic_webxr_permission_page")), + PAGE_LOAD_TIMEOUT_S); + // Be sure to store the stream we're given so that the permission is actually in use, as + // otherwise the toast doesn't show up since another tab isn't actually using the + // permission. + WebXrVrTestFramework.runJavaScriptOrFail( + "requestPermission({audio:true}, true /* storeValue */)", POLL_TIMEOUT_SHORT_MS, + mTestRule.getWebContents()); + PermissionUtils.waitForPermissionPrompt(); + PermissionUtils.acceptPermissionPrompt(); + WebXrVrTestFramework.waitOnJavaScriptStep(mTestRule.getWebContents()); + + if (incognito) { + ThreadUtils.runOnUiThreadBlocking(() -> { + mTestRule.getActivity() + .getTabCreator(true /* incognito */) + .launchUrl("about:blank", TabLaunchType.FROM_LINK); + }); + } else { + mTestRule.loadUrlInNewTab("about:blank"); + } + + mWebXrVrTestFramework.loadUrlAndAwaitInitialization( + WebXrVrTestFramework.getFileUrlForHtmlTestFile("generic_webxr_page"), + PAGE_LOAD_TIMEOUT_S); + mWebXrVrTestFramework.enterSessionWithUserGestureOrFail(mTestRule.getWebContents()); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {}); + + if (teardownServer) { + server.stopAndDestroyServer(); + } + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java index fefb638..04c5c59 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.vr.rules.VrSettingsFile; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction; +import org.chromium.chrome.browser.vr.util.NativeUiUtils; import org.chromium.chrome.browser.vr.util.NfcSimUtils; import org.chromium.chrome.browser.vr.util.VrSettingsServiceUtils; import org.chromium.chrome.browser.vr.util.VrTestRuleUtils; @@ -485,4 +486,24 @@ mWebXrVrTestFramework.executeStepAndWait("stepAfterImmersive()"); mWebXrVrTestFramework.endTest(); } + + /** + * Tests that the "Press app button to exit" toast appears when entering an immersive WebXR for + * VR session with Daydream View paired. + */ + @Test + @MediumTest + @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE) + @CommandLineFlags + .Remove({"enable-webvr"}) + @CommandLineFlags.Add({"enable-features=WebXR"}) + @XrActivityRestriction({XrActivityRestriction.SupportedActivity.CTA}) + public void testAppButtonExitToast() throws InterruptedException { + mWebXrVrTestFramework.loadUrlAndAwaitInitialization( + WebXrVrTestFramework.getFileUrlForHtmlTestFile("generic_webxr_page"), + PAGE_LOAD_TIMEOUT_S); + mWebXrVrTestFramework.enterSessionWithUserGestureOrFail(); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.APP_BUTTON_EXIT_TOAST, true /* visible*/, () -> {}); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java index 42751ef6..77c5b53 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
@@ -223,14 +223,16 @@ throws InterruptedException { final TestVrShellDelegate instance = TestVrShellDelegate.getInstance(); final CountDownLatch resultLatch = new CountDownLatch(1); + final VrShell.UiOperationData operationData = new VrShell.UiOperationData(); + operationData.actionType = UiTestOperationType.UI_ACTIVITY_RESULT; + operationData.resultCallback = () -> { + resultLatch.countDown(); + }; + operationData.timeoutMs = DEFAULT_UI_QUIESCENCE_TIMEOUT_MS; // Run on the UI thread to prevent issues with registering a new callback before // ReportUiOperationResultForTesting has finished. - ThreadUtils.runOnUiThreadBlocking(() -> { - instance.registerUiOperationCallbackForTesting( - UiTestOperationType.UI_ACTIVITY_RESULT, () -> { - resultLatch.countDown(); - }, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, 0 /* unused */); - }); + ThreadUtils.runOnUiThreadBlocking( + () -> { instance.registerUiOperationCallbackForTesting(operationData); }); action.run(); // Wait for any outstanding animations to finish. @@ -243,32 +245,38 @@ } /** - * Runs the given Runnable and waits until the specified element changes its visibility. + * Runs the given Runnable and waits until the specified element matches the requested + * visibility. * * @param elementName The UserFriendlyElementName to wait on to change visibility. + * @param status The visibility status to wait for. * @param action A Runnable containing the action to perform. */ - public static void performActionAndWaitForVisibilityChange( - final int elementName, Runnable action) throws InterruptedException { + public static void performActionAndWaitForVisibilityStatus(final int elementName, + final boolean visible, Runnable action) throws InterruptedException { final TestVrShellDelegate instance = TestVrShellDelegate.getInstance(); final CountDownLatch resultLatch = new CountDownLatch(1); + final VrShell.UiOperationData operationData = new VrShell.UiOperationData(); + operationData.actionType = UiTestOperationType.ELEMENT_VISIBILITY_STATUS; + operationData.resultCallback = () -> { + resultLatch.countDown(); + }; + operationData.timeoutMs = DEFAULT_UI_QUIESCENCE_TIMEOUT_MS; + operationData.elementName = elementName; + operationData.visibility = visible; // Run on the UI thread to prevent issues with registering a new callback before // ReportUiOperationResultForTesting has finished. - ThreadUtils.runOnUiThreadBlocking(() -> { - instance.registerUiOperationCallbackForTesting( - UiTestOperationType.ELEMENT_VISIBILITY_CHANGE, () -> { - resultLatch.countDown(); - }, DEFAULT_UI_QUIESCENCE_TIMEOUT_MS, elementName); - }); + ThreadUtils.runOnUiThreadBlocking( + () -> { instance.registerUiOperationCallbackForTesting(operationData); }); action.run(); // Wait for the result to be reported. resultLatch.await(); int result = instance.getLastUiOperationResultForTesting( - UiTestOperationType.ELEMENT_VISIBILITY_CHANGE); + UiTestOperationType.ELEMENT_VISIBILITY_STATUS); Assert.assertEquals("UI reported non-visibility-changed result '" + uiTestOperationResultToString(result) + "'", - UiTestOperationResult.VISIBILITY_CHANGE, result); + UiTestOperationResult.VISIBILITY_MATCH, result); } /** @@ -310,13 +318,16 @@ final TestVrShellDelegate instance = TestVrShellDelegate.getInstance(); final CountDownLatch resultLatch = new CountDownLatch(1); + final VrShell.UiOperationData operationData = new VrShell.UiOperationData(); + operationData.actionType = UiTestOperationType.FRAME_BUFFER_DUMPED; + operationData.resultCallback = () -> { + resultLatch.countDown(); + }; // Run on the UI thread to prevent issues with registering a new callback before // ReportUiOperationResultForTesting has finished. - ThreadUtils.runOnUiThreadBlocking(() -> { - instance.registerUiOperationCallbackForTesting(UiTestOperationType.FRAME_BUFFER_DUMPED, - () -> { resultLatch.countDown(); }, 0 /* unused */, 0 /* unused */); - }); + ThreadUtils.runOnUiThreadBlocking( + () -> { instance.registerUiOperationCallbackForTesting(operationData); }); instance.saveNextFrameBufferToDiskForTesting(filepathBase); resultLatch.await(); } @@ -372,10 +383,10 @@ return "Timeout (UI activity not started)"; case UiTestOperationResult.TIMEOUT_NO_END: return "Timeout (UI activity not stopped)"; - case UiTestOperationResult.VISIBILITY_CHANGE: - return "Visibility change"; - case UiTestOperationResult.TIMEOUT_NO_CHANGE: - return "Timeout (Element visibility did not change)"; + case UiTestOperationResult.VISIBILITY_MATCH: + return "Visibility match"; + case UiTestOperationResult.TIMEOUT_NO_VISIBILITY_MATCH: + return "Timeout (Element visibility did not match)"; default: return "Unknown result"; }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java index 12ae8b76..80803db 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
@@ -15,7 +15,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.chromium.content_public.common.MediaMetadata.MediaImage; +import static org.chromium.services.media_session.MediaMetadata.MediaImage; import android.graphics.Bitmap; import android.graphics.Rect; @@ -296,4 +296,4 @@ verify(mCallback).onImageDownloaded((Bitmap) isNull()); verify(mCallback, times(0)).onImageDownloaded((Bitmap) isNotNull()); } -} \ No newline at end of file +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerNotificationTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerNotificationTest.java index 842d8761..b26439e4a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerNotificationTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerNotificationTest.java
@@ -26,7 +26,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; /** * JUnit tests for checking MediaNotificationManager presents correct notification to Android
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerServiceLifecycleTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerServiceLifecycleTest.java index 53bba083..18fee49 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerServiceLifecycleTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerServiceLifecycleTest.java
@@ -36,7 +36,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.media.ui.MediaNotificationManager.ListenerService; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.concurrent.TimeoutException;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerTestBase.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerTestBase.java index f2d9962..02564ce 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerTestBase.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationManagerTestBase.java
@@ -38,7 +38,7 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.media.ui.MediaNotificationManager.ListenerService; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.HashMap; import java.util.Map;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java index e961e431..b6ac764 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTestTabHolder.java
@@ -17,7 +17,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.MediaSession; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.Set;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTitleUpdatedTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTitleUpdatedTest.java index 0bf7bcd5..888e5c4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTitleUpdatedTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaNotificationTitleUpdatedTest.java
@@ -23,7 +23,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; import org.chromium.chrome.browser.media.ui.MediaNotificationManager.ListenerService; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; /** * Test of media notifications to see whether the text updates when the tab title changes or the
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 54080f84..f9f314d9 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -107,7 +107,6 @@ #include "content/public/common/content_switches.h" #include "content/public/common/feature_h264_with_openh264_ffmpeg.h" #include "device/base/features.h" -#include "device/gamepad/public/cpp/gamepad_features.h" #include "device/vr/buildflags/buildflags.h" #include "extensions/buildflags/buildflags.h" #include "gpu/config/gpu_finch_features.h" @@ -755,10 +754,10 @@ switches::kEnableUseZoomForDSF, "false"}, }; -const FeatureEntry::Choice kSiteIsolationTrialOptOutChoices[] = { - {flag_descriptions::kSiteIsolationTrialOptOutChoiceDefault, "", ""}, - {flag_descriptions::kSiteIsolationTrialOptOutChoiceOptOut, - switches::kDisableSiteIsolationTrials, ""}, +const FeatureEntry::Choice kSiteIsolationOptOutChoices[] = { + {flag_descriptions::kSiteIsolationOptOutChoiceDefault, "", ""}, + {flag_descriptions::kSiteIsolationOptOutChoiceOptOut, + switches::kDisableSiteIsolation, ""}, }; const FeatureEntry::Choice kTLS13VariantChoices[] = { @@ -1225,26 +1224,6 @@ base::size(kProactiveTabFreezeAndDiscard_DisableHeuristics), nullptr}}; #endif -const FeatureEntry::FeatureParam kGamepadPollingRate100Hz[] = { - {features::kGamepadPollingIntervalParamKey, "10"}}; -const FeatureEntry::FeatureParam kGamepadPollingRate125Hz[] = { - {features::kGamepadPollingIntervalParamKey, "8"}}; -const FeatureEntry::FeatureParam kGamepadPollingRate200Hz[] = { - {features::kGamepadPollingIntervalParamKey, "5"}}; -const FeatureEntry::FeatureParam kGamepadPollingRate250Hz[] = { - {features::kGamepadPollingIntervalParamKey, "4"}}; - -const FeatureEntry::FeatureVariation kGamepadPollingRateVariations[] = { - {"(100 Hz)", kGamepadPollingRate100Hz, base::size(kGamepadPollingRate100Hz), - nullptr}, - {"(125 Hz)", kGamepadPollingRate125Hz, base::size(kGamepadPollingRate125Hz), - nullptr}, - {"(200 Hz)", kGamepadPollingRate200Hz, base::size(kGamepadPollingRate200Hz), - nullptr}, - {"(250 Hz)", kGamepadPollingRate250Hz, base::size(kGamepadPollingRate250Hz), - nullptr}, -}; - #if defined(OS_ANDROID) const FeatureEntry::FeatureParam kNewNetErrorPageUIContentList = { features::kNewNetErrorPageUIAlternateParameterName, @@ -2202,13 +2181,15 @@ flag_descriptions::kSSLCommittedInterstitialsName, flag_descriptions::kSSLCommittedInterstitialsDescription, kOsAll, FEATURE_VALUE_TYPE(features::kSSLCommittedInterstitials)}, +#if defined(OS_ANDROID) {"enable-site-per-process", flag_descriptions::kStrictSiteIsolationName, - flag_descriptions::kStrictSiteIsolationDescription, kOsAll, + flag_descriptions::kStrictSiteIsolationDescription, kOsAndroid, SINGLE_VALUE_TYPE(switches::kSitePerProcess)}, +#endif {"site-isolation-trial-opt-out", - flag_descriptions::kSiteIsolationTrialOptOutName, - flag_descriptions::kSiteIsolationTrialOptOutDescription, kOsAll, - MULTI_VALUE_TYPE(kSiteIsolationTrialOptOutChoices)}, + flag_descriptions::kSiteIsolationOptOutName, + flag_descriptions::kSiteIsolationOptOutDescription, kOsAll, + MULTI_VALUE_TYPE(kSiteIsolationOptOutChoices)}, {"enable-use-zoom-for-dsf", flag_descriptions::kEnableUseZoomForDsfName, flag_descriptions::kEnableUseZoomForDsfDescription, kOsAll, MULTI_VALUE_TYPE(kEnableUseZoomForDSFChoices)}, @@ -4200,12 +4181,6 @@ FEATURE_VALUE_TYPE(features::kArcCupsApi)}, #endif // OS_CHROMEOS - {"gamepad-polling-rate", flag_descriptions::kGamepadPollingRateName, - flag_descriptions::kGamepadPollingRateDescription, kOsDesktop, - FEATURE_WITH_PARAMS_VALUE_TYPE(features::kGamepadPollingInterval, - kGamepadPollingRateVariations, - "GamepadPollingInterval")}, - #if defined(OS_CHROMEOS) {"enable-drive-fs", flag_descriptions::kEnableDriveFsName, flag_descriptions::kEnableDriveFsDescription, kOsCrOS,
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc index 88776a2a..8383122c 100644 --- a/chrome/browser/android/vr/vr_shell.cc +++ b/chrome/browser/android/vr/vr_shell.cc
@@ -1266,19 +1266,21 @@ base::android::ConvertJavaStringToUTF8(env, filepath_base))); } -void VrShell::WatchElementForVisibilityChangeForTesting( +void VrShell::WatchElementForVisibilityStatusForTesting( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint element_name, - jint timeout_ms) { + jint timeout_ms, + jboolean visibility) { VisibilityChangeExpectation visibility_expectation; visibility_expectation.element_name = static_cast<UserFriendlyElementName>(element_name); visibility_expectation.timeout_ms = timeout_ms; + visibility_expectation.visibility = visibility; PostToGlThread( FROM_HERE, base::BindOnce( - &BrowserRenderer::WatchElementForVisibilityChangeForTesting, + &BrowserRenderer::WatchElementForVisibilityStatusForTesting, gl_thread_->GetBrowserRenderer(), visibility_expectation)); }
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h index f49cb7e..5c719f848 100644 --- a/chrome/browser/android/vr/vr_shell.h +++ b/chrome/browser/android/vr/vr_shell.h
@@ -285,11 +285,12 @@ const base::android::JavaParamRef<jobject>& obj, jstring filepath_base); - void WatchElementForVisibilityChangeForTesting( + void WatchElementForVisibilityStatusForTesting( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint element_name, - jint timeout_ms); + jint timeout_ms, + jboolean visibility); void ReportUiOperationResultForTesting(UiTestOperationType action_type, UiTestOperationResult result);
diff --git a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc index 43b6a2c2..8bfb59e 100644 --- a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc
@@ -126,7 +126,9 @@ TestLoadApiHelper("testLoadAPISameIdDifferentSrc"); } -IN_PROC_BROWSER_TEST_F(ExtensionViewLoadApiTest, LoadAPILoadOtherExtension) { +// TODO(crbug.com/810225): Test is flaky. +IN_PROC_BROWSER_TEST_F(ExtensionViewLoadApiTest, + DISABLED_LoadAPILoadOtherExtension) { TestLoadApiHelper("testLoadAPILoadOtherExtension"); } @@ -146,7 +148,8 @@ TestLoadApiHelper("testQueuedLoadAPIFunction"); } +// TODO(crbug.com/810225): Test is flaky. IN_PROC_BROWSER_TEST_F(ExtensionViewLoadApiTest, - QueuedLoadAPILoadOtherExtension) { + DISABLED_QueuedLoadAPILoadOtherExtension) { TestLoadApiHelper("testQueuedLoadAPILoadOtherExtension"); }
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 00ca74f..71f95fc 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1165,16 +1165,15 @@ } } - // The admin should also be able to use these policies to override trials that - // will try to turn site isolation on per default. - // Note that disabling either SitePerProcess or IsolateOrigins via policy will - // disable both types of field trials. + // The admin should also be able to use these policies to force Site Isolation + // off. Note that disabling either SitePerProcess or IsolateOrigins via + // policy will disable both types of isolation. if ((local_state->IsManagedPreference(prefs::kSitePerProcess) && !local_state->GetBoolean(prefs::kSitePerProcess)) || (local_state->IsManagedPreference(prefs::kIsolateOrigins) && local_state->GetString(prefs::kIsolateOrigins).empty())) { base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kDisableSiteIsolationTrials); + switches::kDisableSiteIsolation); } // ChromeOS needs ui::ResourceBundle::InitSharedInstance to be called before
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 9f8692b..1864097 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2598,7 +2598,7 @@ } #if defined(OS_CHROMEOS) -void ChromeContentBrowserClient::OnUsedTrustAnchor( +void ChromeContentBrowserClient::OnTrustAnchorUsed( const std::string& username_hash) { policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(username_hash); }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index cc560e0..e37d72b 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -258,7 +258,7 @@ const url::Origin& embedding_origin) override; std::string GetWebBluetoothBlocklist() override; #if defined(OS_CHROMEOS) - void OnUsedTrustAnchor(const std::string& username_hash) override; + void OnTrustAnchorUsed(const std::string& username_hash) override; #endif net::CookieStore* OverrideCookieStoreForURL( const GURL& url,
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc index 87572d93..d99a5d9 100644 --- a/chrome/browser/chrome_content_browser_client_browsertest.cc +++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -182,7 +182,7 @@ return true; if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)) + switches::kDisableSiteIsolation)) return true; return false;
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc index d7f47d8..77fc5594 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc
@@ -49,11 +49,19 @@ return b.is_null() || a < b; } +// Implements the modulo operation. E.g. modulo(10, 7) == 3, modulo(-1, 7) == 6. +int Modulo(int dividend, int divisor) { + int remainder = dividend % divisor; + if (remainder < 0) + remainder += divisor; + return remainder; +} + // Shifts the current weekday, if the value is positive shifts forward and if // negative backwards. Weekday WeekdayShift(Weekday current_day, int shift) { - return static_cast<Weekday>((static_cast<int>(current_day) + shift) % - static_cast<int>(Weekday::kCount)); + return static_cast<Weekday>(Modulo(static_cast<int>(current_day) + shift, + static_cast<int>(Weekday::kCount))); } // Returns usage limit reset time or default value if |time_usage_limit| is
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc index dfff0f0..7f15c1d5 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc
@@ -878,6 +878,141 @@ AssertEqState(expected_state_one, state_one); } +// Test if an overnight time window limit applies to the following day. +TEST_F(UsageTimeLimitProcessorTest, GetStateWithPreviousDayTimeWindowLimit) { + std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("GMT")); + + // Setup time window limit. + std::string last_updated = CreatePolicyTimestamp("1 Jan 2018 8:00 GMT"); + base::Value saturday_time_limit = + CreateTimeWindow(base::Value("SATURDAY"), CreateTime(21, 0), + CreateTime(8, 30), base::Value(last_updated)); + + base::Value window_limit_entries(base::Value::Type::LIST); + window_limit_entries.GetList().push_back(std::move(saturday_time_limit)); + + base::Value time_window_limit(base::Value::Type::DICTIONARY); + time_window_limit.SetKey("entries", std::move(window_limit_entries)); + + // Setup time usage limit. + base::Value time_usage_limit = base::Value(base::Value::Type::DICTIONARY); + time_usage_limit.SetKey("reset_at", CreateTime(8, 0)); + + // Setup policy. + std::unique_ptr<base::Value> time_limit = + std::make_unique<base::Value>(base::Value::Type::DICTIONARY); + time_limit->SetKey("time_window_limit", std::move(time_window_limit)); + time_limit->SetKey("time_usage_limit", std::move(time_usage_limit)); + + std::unique_ptr<base::DictionaryValue> time_limit_dictionary = + base::DictionaryValue::From(std::move(time_limit)); + + // Check that device is locked. + base::Time time_one = TimeFromString("Sun, 7 Jan 2018 8:00 GMT"); + State state_one = + GetState(time_limit_dictionary, base::TimeDelta::FromMinutes(80), + time_one, time_one, timezone.get(), base::nullopt); + + State expected_state_one; + expected_state_one.is_locked = true; + expected_state_one.active_policy = ActivePolicies::kFixedLimit; + expected_state_one.is_time_usage_limit_enabled = false; + expected_state_one.next_state_change_time = + TimeFromString("Sun, 7 Jan 2018 8:30 GMT"); + expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; + expected_state_one.next_unlock_time = + TimeFromString("Sun, 7 Jan 2018 8:30 GMT"); + expected_state_one.last_state_changed = base::Time(); + + AssertEqState(expected_state_one, state_one); +} + +// Test if a time usage limit applies to the morning of the following day. +TEST_F(UsageTimeLimitProcessorTest, GetStateWithPreviousDayTimeUsageLimit) { + std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("GMT")); + + // Setup time usage limit. + std::string last_updated = CreatePolicyTimestamp("1 Jan 2018 8:00 GMT"); + base::Value saturday_time_usage = + CreateTimeUsage(base::Value(120), base::Value(last_updated)); + + base::Value time_usage_limit = base::Value(base::Value::Type::DICTIONARY); + time_usage_limit.SetKey("saturday", std::move(saturday_time_usage)); + time_usage_limit.SetKey("reset_at", CreateTime(6, 0)); + + // Setup policy. + std::unique_ptr<base::Value> time_limit = + std::make_unique<base::Value>(base::Value::Type::DICTIONARY); + time_limit->SetKey("time_usage_limit", std::move(time_usage_limit)); + + std::unique_ptr<base::DictionaryValue> time_limit_dictionary = + base::DictionaryValue::From(std::move(time_limit)); + + // Check that device is locked. + base::Time time_one = TimeFromString("Sun, 7 Jan 2018 4:00 GMT"); + State state_one = + GetState(time_limit_dictionary, base::TimeDelta::FromMinutes(120), + time_one, time_one, timezone.get(), base::nullopt); + + State expected_state_one; + expected_state_one.is_locked = true; + expected_state_one.active_policy = ActivePolicies::kUsageLimit; + expected_state_one.is_time_usage_limit_enabled = true; + expected_state_one.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_one.time_usage_limit_started = time_one; + expected_state_one.next_state_change_time = + TimeFromString("Sun, 7 Jan 2018 6:00 GMT"); + expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; + expected_state_one.next_unlock_time = + TimeFromString("Sun, 7 Jan 2018 6:00 GMT"); + expected_state_one.last_state_changed = base::Time(); + + AssertEqState(expected_state_one, state_one); +} + +// Test if a time usage limit applies to the current night. +TEST_F(UsageTimeLimitProcessorTest, GetStateWithWeekendTimeUsageLimit) { + std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("PST")); + + // Setup time usage limit. + std::string last_updated = CreatePolicyTimestamp("1 Jan 2018 8:00 PST"); + base::Value saturday_time_usage = + CreateTimeUsage(base::Value(120), base::Value(last_updated)); + + base::Value time_usage_limit = base::Value(base::Value::Type::DICTIONARY); + time_usage_limit.SetKey("saturday", std::move(saturday_time_usage)); + time_usage_limit.SetKey("reset_at", CreateTime(6, 0)); + + // Setup policy. + std::unique_ptr<base::Value> time_limit = + std::make_unique<base::Value>(base::Value::Type::DICTIONARY); + time_limit->SetKey("time_usage_limit", std::move(time_usage_limit)); + + std::unique_ptr<base::DictionaryValue> time_limit_dictionary = + base::DictionaryValue::From(std::move(time_limit)); + + // Check that device is locked. + base::Time time_one = TimeFromString("Sat, 6 Jan 2018 20:00 PST"); + State state_one = + GetState(time_limit_dictionary, base::TimeDelta::FromMinutes(120), + time_one, time_one, timezone.get(), base::nullopt); + + State expected_state_one; + expected_state_one.is_locked = true; + expected_state_one.active_policy = ActivePolicies::kUsageLimit; + expected_state_one.is_time_usage_limit_enabled = true; + expected_state_one.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_one.time_usage_limit_started = time_one; + expected_state_one.next_state_change_time = + TimeFromString("Sun, 7 Jan 2018 6:00 PST"); + expected_state_one.next_state_active_policy = ActivePolicies::kNoActivePolicy; + expected_state_one.next_unlock_time = + TimeFromString("Sun, 7 Jan 2018 6:00 PST"); + expected_state_one.last_state_changed = base::Time(); + + AssertEqState(expected_state_one, state_one); +} + // Test GetExpectedResetTime with an empty policy. TEST_F(UsageTimeLimitProcessorTest, GetExpectedResetTimeWithEmptyPolicy) { std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("GMT"));
diff --git a/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc b/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc index bf5eb2ea..aa2cc9c 100644 --- a/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/users_private/users_private_apitest.cc
@@ -242,7 +242,6 @@ chromeos::ScreenLocker::Show(); std::unique_ptr<chromeos::test::ScreenLockerTester> tester( chromeos::ScreenLocker::GetTester()); - tester->EmulateWindowManagerReady(); content::WindowedNotificationObserver lock_state_observer( chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, content::NotificationService::AllSources());
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc index 06fdf5a..2a22e00d 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -6,8 +6,6 @@ #include <utility> -#include "apps/app_lifetime_monitor.h" -#include "apps/app_lifetime_monitor_factory.h" #include "base/bind.h" #include "base/command_line.h" #include "base/guid.h"
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc index 6a49572..dde620d 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -102,7 +102,6 @@ void LockScreen(test::ScreenLockerTester* tester) { ScreenLocker::Show(); - tester->EmulateWindowManagerReady(); content::WindowedNotificationObserver lock_state_observer( chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, content::NotificationService::AllSources()); @@ -158,7 +157,6 @@ return; ScreenLocker::Show(); std::unique_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); - tester->EmulateWindowManagerReady(); content::WindowedNotificationObserver lock_state_observer( chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, content::NotificationService::AllSources()); @@ -167,13 +165,6 @@ EXPECT_EQ(session_manager::SessionState::LOCKED, session_manager::SessionManager::Get()->session_state()); - // Test to make sure that the widget is actually appearing and is of - // reasonable size, preventing a regression of - // http://code.google.com/p/chromium-os/issues/detail?id=5987 - gfx::Rect lock_bounds = tester->GetChildWidget()->GetWindowBoundsInScreen(); - EXPECT_GT(lock_bounds.width(), 10); - EXPECT_GT(lock_bounds.height(), 10); - UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR, user_manager::StubAccountId()); user_context.SetKey(Key("pass")); @@ -238,7 +229,6 @@ { Waiter waiter(browser()); ScreenLocker::Show(); - tester->EmulateWindowManagerReady(); waiter.Wait(true /* locked */, true /* full screen */); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_FALSE(window_state->GetHideShelfWhenFullscreen()); @@ -284,7 +274,6 @@ { Waiter waiter(browser()); ScreenLocker::Show(); - tester->EmulateWindowManagerReady(); waiter.Wait(true /* locked */, false /* full screen */); EXPECT_FALSE(browser_window->IsFullscreen()); EXPECT_TRUE(tester->IsLocked()); @@ -327,27 +316,4 @@ EXPECT_TRUE(VerifyLockScreenDismissed()); } -// TODO(flackr): Find out why the RenderView isn't getting the escape press -// and re-enable this test (currently this test is flaky). -IN_PROC_BROWSER_TEST_F(ScreenLockerTest, DISABLED_TestEscape) { - std::unique_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); - LockScreen(tester.get()); - - EXPECT_EQ( - 1, fake_session_manager_client_->notify_lock_screen_shown_call_count()); - - tester->SetPassword("password"); - EXPECT_EQ("password", tester->GetPassword()); - // Escape clears the password. - SimulateKeyPress(tester->GetWidget(), ui::VKEY_ESCAPE); - content::RunAllPendingInMessageLoop(); - EXPECT_EQ("", tester->GetPassword()); - - // Close the locker to match expectations. - ScreenLocker::Hide(); - content::RunAllPendingInMessageLoop(); - EXPECT_FALSE(tester->IsLocked()); - EXPECT_TRUE(VerifyLockScreenDismissed()); -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc index 3e4b629..1049c29 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_tester.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.cc
@@ -98,9 +98,6 @@ void SetPassword(const std::string& password) override; std::string GetPassword() override; void EnterPassword(const std::string& password) override; - void EmulateWindowManagerReady() override; - views::Widget* GetWidget() const override; - views::Widget* GetChildWidget() const override; private: friend class chromeos::ScreenLocker; @@ -159,16 +156,6 @@ login.WaitForAttempt(); } -void WebUIScreenLockerTester::EmulateWindowManagerReady() {} - -views::Widget* WebUIScreenLockerTester::GetWidget() const { - return webui_screen_locker()->lock_window_; -} - -views::Widget* WebUIScreenLockerTester::GetChildWidget() const { - return webui_screen_locker()->lock_window_; -} - content::RenderFrameHost* WebUIScreenLockerTester::GetMainFrame() const { return webui()->GetWebContents()->GetMainFrame(); }
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_tester.h b/chrome/browser/chromeos/login/lock/screen_locker_tester.h index 554407b..da3a2e4 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_tester.h +++ b/chrome/browser/chromeos/login/lock/screen_locker_tester.h
@@ -7,10 +7,6 @@ #include <string> -namespace views { -class Widget; -} // namespace views - namespace chromeos { class UserContext; @@ -38,14 +34,6 @@ // Emulates entring a password. virtual void EnterPassword(const std::string& password) = 0; - - // Emulates the ready message from window manager. - virtual void EmulateWindowManagerReady() = 0; - - // Returns the widget for screen locker window. - virtual views::Widget* GetWidget() const = 0; - - virtual views::Widget* GetChildWidget() const = 0; }; } // namespace test
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 3e7124b4..28b9a6f 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -439,11 +439,10 @@ ? isolate_origins_pref->GetValue()->GetString() : std::string(); - // The admin should also be able to use these policies to override trials that - // will try to turn site isolation on per default. - // Note that disabling either SitePerProcess or IsolateOrigins via policy will - // disable both types of field trials. - bool disable_site_isolation_trials = + // The admin should also be able to use these policies to force site isolation + // off. Note that disabling either SitePerProcess or IsolateOrigins via + // policy will disable both types of isolation. + bool disable_site_isolation = (site_per_process_pref->IsManaged() && !site_per_process_pref->GetValue()->GetBool()) || (isolate_origins_pref->IsManaged() && isolate_origins.empty()); @@ -457,8 +456,8 @@ // We use the policy-style sentinels because these values originate from // policy, and because login_manager uses the same sentinels when adding the // login-screen site isolation flags. - bool use_policy_sentinels = site_per_process || !isolate_origins.empty() || - disable_site_isolation_trials; + bool use_policy_sentinels = + site_per_process || !isolate_origins.empty() || disable_site_isolation; if (use_policy_sentinels) user_flags->AppendSwitch(chromeos::switches::kPolicySwitchesBegin); @@ -474,8 +473,8 @@ user_profile_prefs->GetString(prefs::kIsolateOrigins)); } - if (disable_site_isolation_trials) { - user_flags->AppendSwitch(::switches::kDisableSiteIsolationTrials); + if (disable_site_isolation) { + user_flags->AppendSwitch(::switches::kDisableSiteIsolation); } if (use_policy_sentinels) {
diff --git a/chrome/browser/chromeos/shutdown_policy_browsertest.cc b/chrome/browser/chromeos/shutdown_policy_browsertest.cc index 4cca90d..0390667 100644 --- a/chrome/browser/chromeos/shutdown_policy_browsertest.cc +++ b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
@@ -239,7 +239,6 @@ // Bring up the locker screen. ScreenLocker::Show(); std::unique_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); - tester->EmulateWindowManagerReady(); content::WindowedNotificationObserver lock_state_observer( chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, content::NotificationService::AllSources());
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 729d9dd..4b6ece32 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -363,9 +363,9 @@ bindings_(bindings), loader_(std::move(loader)), callback_(callback) { - loader_->DownloadAsStream(url_loader_factory, this); loader_->SetOnResponseStartedCallback(base::BindOnce( &NetworkResourceLoader::OnResponseStarted, base::Unretained(this))); + loader_->DownloadAsStream(url_loader_factory, this); } private:
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 9dd69cc..aa48112 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -317,7 +317,7 @@ const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; const char kGoodCrxPath[] = "extensions/good.crx"; -const char kLargeThemeCrxId[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; +const char kLargeThemeCrxId[] = "ibcijncamhmjjdodjamgiipcgnnaeagd"; const char kLargeThemePath[] = "extensions/theme2.crx"; // User script file used in tests.
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc index 593141f..d925971 100644 --- a/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc +++ b/chrome/browser/extensions/api/braille_display_private/braille_display_private_apitest.cc
@@ -306,7 +306,6 @@ void LockScreen(ScreenLockerTester* tester) { ScreenLocker::Show(); - tester->EmulateWindowManagerReady(); content::WindowedNotificationObserver lock_state_observer( chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, content::NotificationService::AllSources());
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index e1ecf59..81a411e6 100644 --- a/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -362,7 +362,7 @@ ASSERT_TRUE(RunInstallTest("theme.html", "../../theme.crx")); listener.Wait(); ASSERT_TRUE(listener.received_success()); - ASSERT_EQ("iamefpfkojoapidjnbafmgkgncegbkad", listener.id()); + ASSERT_EQ("idlfhncioikpdnlhnmcjogambnefbbfp", listener.id()); } // Tests that an error is properly reported when an empty crx is returned.
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc index afdade4..5028d67 100644 --- a/chrome/browser/extensions/extension_service_sync_unittest.cc +++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -87,11 +87,11 @@ const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf"; const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; -const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh"; +const char good2048[] = "dfhpodpjggiioolfhoimofdbfjibmedp"; const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln"; const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo"; -const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; +const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd"; ExtensionSyncData GetDisableSyncData(const Extension& extension, int disable_reasons) {
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 2c5ad02..e204c50e 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -168,13 +168,13 @@ const char good1[] = "hpiknbiabeeppbpihjehijgoemciehgk"; const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa"; const char all_zero[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; -const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh"; +const char good2048[] = "dfhpodpjggiioolfhoimofdbfjibmedp"; const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; const char minimal_platform_app_crx[] = "jjeoclcdfjddkdjokiejckgcildcflpp"; const char hosted_app[] = "kbmnembihfiondgfjekmnmcbddelicoi"; const char page_action[] = "dpfmafkdlbmopmcepgpjkpldjbghdibm"; -const char theme_crx[] = "iamefpfkojoapidjnbafmgkgncegbkad"; -const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf"; +const char theme_crx[] = "idlfhncioikpdnlhnmcjogambnefbbfp"; +const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd"; const char permissions_crx[] = "eagpmdpfmaekmmcejjbmjoecnejeiiin"; const char updates_from_webstore[] = "akjooamlhcgeopfifcmlggaebeocgokj"; const char updates_from_webstore2[] = "oolblhbomdbcpmafphaodhjfcgbihcdg";
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 2910368..ba57b81 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1010,11 +1010,6 @@ const char kGamepadExtensionsName[] = "Gamepad Extensions"; const char kGamepadExtensionsDescription[] = "Enables experimental extensions to the Gamepad APIs."; -const char kGamepadPollingRateName[] = "Override Gamepad Polling Rate"; -const char kGamepadPollingRateDescription[] = - "Overrides the rate at which gamepad input devices are polled. Increasing " - "the polling rate improves the average latency of button and axis inputs " - "but may negatively affect performance."; const char kGamepadVibrationName[] = "Gamepad Vibration"; const char kGamepadVibrationDescription[] = "Enables haptic vibration effects on supported gamepads."; @@ -1736,31 +1731,32 @@ const char kSingleTabModeDescription[] = "Windows with a single tab receive a special, minimal visual treatment."; +#if defined(OS_ANDROID) const char kStrictSiteIsolationName[] = "Strict site isolation"; const char kStrictSiteIsolationDescription[] = "Security mode that enables site isolation for all sites (SitePerProcess). " "In this mode, each renderer process will contain pages from at most one " - "site, using out-of-process iframes when needed. NOTE: Site isolation is " - "enabled by default on desktop platforms regardless of how this flag is " - "set; see chrome://process-internals for whether it is currently enabled. " + "site, using out-of-process iframes when needed. " + "Check chrome://process-internals to see the current isolation mode. " "Setting this flag to 'Enabled' turns on site isolation regardless of the " "default. Here, 'Disabled' is a legacy value that actually means " "'Default,' in which case site isolation may be already enabled based on " "platform, enterprise policy, or field trial. See also " "#site-isolation-trial-opt-out for how to disable site isolation for " "testing."; +#endif -const char kSiteIsolationTrialOptOutName[] = "Site isolation trial opt-out"; -const char kSiteIsolationTrialOptOutDescription[] = - "Opts out of field trials and defaults that enable site isolation modes " +const char kSiteIsolationOptOutName[] = "Disable site isolation"; +const char kSiteIsolationOptOutDescription[] = + "Disables site isolation " "(SitePerProcess, IsolateOrigins, etc). Intended for diagnosing bugs that " "may be due to out-of-process iframes. Opt-out has no effect if site " - "isolation is force-enabled via #enable-site-per-process or enterprise " - "policy. Caution: this disables important mitigations for the Spectre CPU " + "isolation is force-enabled using a command line switch or using an " + "enterprise policy. " + "Caution: this disables important mitigations for the Spectre CPU " "vulnerability affecting most computers."; -const char kSiteIsolationTrialOptOutChoiceDefault[] = "Default"; -const char kSiteIsolationTrialOptOutChoiceOptOut[] = - "Opt-out (not recommended)"; +const char kSiteIsolationOptOutChoiceDefault[] = "Default"; +const char kSiteIsolationOptOutChoiceOptOut[] = "Disabled (not recommended)"; const char kSiteSettings[] = "Site settings"; const char kSiteSettingsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 1969b80b6..950f3d496 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -618,8 +618,6 @@ extern const char kGamepadExtensionsName[]; extern const char kGamepadExtensionsDescription[]; -extern const char kGamepadPollingRateName[]; -extern const char kGamepadPollingRateDescription[]; extern const char kGamepadVibrationName[]; extern const char kGamepadVibrationDescription[]; @@ -1048,13 +1046,15 @@ extern const char kSingleTabMode[]; extern const char kSingleTabModeDescription[]; +#if defined(OS_ANDROID) extern const char kStrictSiteIsolationName[]; extern const char kStrictSiteIsolationDescription[]; +#endif -extern const char kSiteIsolationTrialOptOutName[]; -extern const char kSiteIsolationTrialOptOutDescription[]; -extern const char kSiteIsolationTrialOptOutChoiceDefault[]; -extern const char kSiteIsolationTrialOptOutChoiceOptOut[]; +extern const char kSiteIsolationOptOutName[]; +extern const char kSiteIsolationOptOutDescription[]; +extern const char kSiteIsolationOptOutChoiceDefault[]; +extern const char kSiteIsolationOptOutChoiceOptOut[]; extern const char kSiteSettings[]; extern const char kSiteSettingsDescription[];
diff --git a/chrome/browser/policy/site_isolation_policy_browsertest.cc b/chrome/browser/policy/site_isolation_policy_browsertest.cc index 642908c..5013fa5c 100644 --- a/chrome/browser/policy/site_isolation_policy_browsertest.cc +++ b/chrome/browser/policy/site_isolation_policy_browsertest.cc
@@ -144,7 +144,7 @@ protected: NoOverrideSitePerProcessPolicyBrowserTest() {} void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kDisableSiteIsolationTrials); + command_line->AppendSwitch(switches::kDisableSiteIsolation); } private: @@ -209,7 +209,7 @@ if (content::AreAllSitesIsolatedForTesting()) return; ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)); + switches::kDisableSiteIsolation)); Expectations expectations[] = { {"https://foo.com/noodles.html", false}, {"http://example.org/pumpkins.html", false}, @@ -217,15 +217,9 @@ CheckExpectations(expectations, arraysize(expectations)); } -// https://crbug.com/833423: The test is incompatible with the -// not_site_per_process_browser_tests step on the trybots. -#if defined(OS_LINUX) -#define MAYBE_NoPolicyNoTrialsFlags DISABLED_NoPolicyNoTrialsFlags -#else -#define MAYBE_NoPolicyNoTrialsFlags NoPolicyNoTrialsFlags -#endif -IN_PROC_BROWSER_TEST_F(SiteIsolationPolicyBrowserTest, - MAYBE_NoPolicyNoTrialsFlags) { +IN_PROC_BROWSER_TEST_F(SiteIsolationPolicyBrowserTest, NoPolicyNoTrialsFlags) { + // The switch to disable Site Isolation should be missing by default (i.e. + // without an explicit enterprise policy). ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)); + switches::kDisableSiteIsolation)); }
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py index bbc0771..e9b9ed8 100644 --- a/chrome/browser/policy/test/policy_testserver.py +++ b/chrome/browser/policy/test/policy_testserver.py
@@ -375,7 +375,9 @@ settings.download_url = urlparse.urljoin( self.server.GetBaseURL(), 'externalpolicydata?key=%s' % policy_key) settings.secure_hash = hashlib.sha256(data).digest() - return settings.SerializeToString() + return settings.SerializeToString() + else: + return None def CheckGoogleLogin(self): """Extracts the auth token from the request and returns it. The token may @@ -855,14 +857,17 @@ if field.type == field.TYPE_BOOL: assert type(field_value) == bool elif field.type == field.TYPE_STRING: - assert type(field_value) == str or type(field_value) == unicode + assert type(field_value) in [str, unicode] + elif field.type == field.TYPE_BYTES: + assert type(field_value) in [str, unicode] + field_value = field_value.decode('hex') elif (field.type == field.TYPE_INT64 or field.type == field.TYPE_INT32 or field.type == field.TYPE_ENUM): assert type(field_value) == int else: return False - group_message.__setattr__(field.name, field_value) + setattr(group_message, field.name, field_value) return True def SetProtobufMessageField(self, group_message, field, field_value): @@ -881,6 +886,25 @@ elif not self.SetProtoField(group_message, field, field_value): raise Exception('Unknown field type %s' % field.type) + def GatherExtensionPolicySettings(self, settings, policies): + """Copies all the policies from a dictionary into a protobuf of type + ExternalPolicyData. + + Args: + settings: The destination: a ExternalPolicyData protobuf. + policies: The source: a dictionary containing the extension policies. + """ + for field in settings.DESCRIPTOR.fields: + # |field| is the entry for a specific policy in the top-level + # ExternalPolicyData proto. + field_value = policies.get(field.name) + if field_value is None: + continue + + field_descriptor = settings.DESCRIPTOR.fields_by_name[field.name] + self.SetProtobufMessageField(settings, field_descriptor, + field_value) + def GatherDevicePolicySettings(self, settings, policies): """Copies all the policies from a dictionary into a protobuf of type CloudDeviceSettingsProto. @@ -953,6 +977,12 @@ # Send one PolicyFetchResponse for each extension that has # configuration data at the server. ids = self.server.ListMatchingComponents(request.policy_type) + if not ids: + # Fetch the ids from the policy JSON, if none in the config directory. + policy = self.server.GetPolicies() + ext_policies = policy.get(request.policy_type, {}) + ids = ext_policies.keys() + for settings_entity_id in ids: # Reuse the extension policy request, to trigger the same signature # type in the response. @@ -1009,6 +1039,11 @@ payload = self.server.ReadPolicyFromDataDir(policy_key, settings) if payload is None: payload = self.CreatePolicyForExternalPolicyData(policy_key) + if payload is None: + ext_policies = policy.get(msg.policy_type, {}) + policies = ext_policies.get(msg.settings_entity_id, {}) + self.GatherExtensionPolicySettings(settings, policies) + payload = settings.SerializeToString() else: response.error_code = 400 response.error_message = 'Invalid policy type'
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js index a6fa438e..ee35c60 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/kbexplorer.js
@@ -59,6 +59,8 @@ cvox.ChromeVoxKbHandler.commandHandler = cvox.KbExplorer.onCommand; $('instruction').focus(); + + cvox.KbExplorer.output(Msgs.getMsg('learn_mode_intro')); }; @@ -74,8 +76,7 @@ // Allow Ctrl+W or escape to be handled. if ((evt.key == 'w' && evt.ctrlKey) || evt.key == 'Escape') { - cvox.KbExplorer.resetListeners_(); - window.close(); + cvox.KbExplorer.close_(); return true; } @@ -92,6 +93,7 @@ * @param {Event} evt key event. */ cvox.KbExplorer.onKeyUp = function(evt) { + cvox.KbExplorer.maybeClose_(); cvox.KbExplorer.clearRange(); evt.preventDefault(); evt.stopPropagation(); @@ -112,6 +114,7 @@ * @param {cvox.BrailleKeyEvent} evt The key event. */ cvox.KbExplorer.onBrailleKeyEvent = function(evt) { + cvox.KbExplorer.maybeClose_(); var msgid; var msgArgs = []; var text; @@ -200,6 +203,7 @@ * defined in ui/accessibility/ax_enums.idl */ cvox.KbExplorer.onAccessibilityGesture = function(gesture) { + cvox.KbExplorer.maybeClose_(); var gestureData = GestureCommandData.GESTURE_COMMAND_MAP[gesture]; if (gestureData) cvox.KbExplorer.onCommand(gestureData.command); @@ -252,3 +256,25 @@ backgroundWindow['BrailleCommandHandler']['setEnabled'](true); backgroundWindow['GestureCommandHandler']['setEnabled'](true); }; + +/** @private */ +cvox.KbExplorer.maybeClose_ = function() { + // Reset listeners and close this page if we somehow move outside of the + // explorer window. + chrome.windows.getLastFocused({populate: true}, (focusedWindow) => { + if (focusedWindow && focusedWindow.focused && + focusedWindow.tabs.find((tab) => { + return tab.url == location.href; + })) + return; + + cvox.KbExplorer.close_(); + }); +}; + +/** @private */ +cvox.KbExplorer.close_ = function() { + cvox.KbExplorer.output(Msgs.getMsg('learn_mode_outtro')); + cvox.KbExplorer.resetListeners_(); + window.close(); +};
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index f6de05aba..9455525 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -495,6 +495,9 @@ } var cur = ChromeVoxState.instance.currentRange; + if (!cur) + return; + if (AutomationUtil.isDescendantOf(cur.start.node, evt.target) || AutomationUtil.isDescendantOf(cur.end.node, evt.target)) { new Output().withLocation(cur, null, evt.type).go();
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index bccc6e7..3d1cc530 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -3092,6 +3092,12 @@ <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_CLICK_GESTURE"> Double tap with one finger </message> + <message desc="Describes Learn Mode when the mode is initially entered." name="IDS_CHROMEVOX_LEARN_MODE_INTRO"> + Starting Learn Mode. Press a qwerty key, refreshable braille key, or touch gesture to learn its function. Press control with w or escape to exit. + </message> + <message desc="Output when leaving Learn Mode." name="IDS_CHROMEVOX_LEARN_MODE_OUTTRO"> + Stopping Learn Mode. + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js index d42701a0..4fa520cc 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
@@ -38,10 +38,10 @@ return; this.$.emailChooser.bookmarkBarWasShown = bookmarkBarShown; - this.$.emailChooser.addBookmark(); + this.$.emailChooser.initializeSection(); }); } else { - this.$.emailChooser.removeBookmark(); + this.$.emailChooser.finalizeSection(); } }, });
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc index 8014598f..cf3b5bf 100644 --- a/chrome/browser/site_details_browsertest.cc +++ b/chrome/browser/site_details_browsertest.cc
@@ -579,13 +579,8 @@ ElementsAre(Bucket(12, 1), Bucket(29, 1), Bucket(68, 1)))); } -// Flaky on Windows, Mac and ChromeOS. crbug.com/671891 -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) -#define MAYBE_IsolateExtensions DISABLED_IsolateExtensions -#else -#define MAYBE_IsolateExtensions IsolateExtensions -#endif -IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, MAYBE_IsolateExtensions) { +// TODO(crbug.com/671891): This test is flaky. +IN_PROC_BROWSER_TEST_F(SiteDetailsBrowserTest, DISABLED_IsolateExtensions) { // We start on "about:blank", which should be credited with a process in this // case. scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 0c1c9bf..9033898 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -3962,16 +3962,10 @@ security_info.content_with_cert_errors_status); } -// Flaky on Windows 7 (dbg) trybot, see https://crbug.com/443374. -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_MixedContentSettings DISABLED_MixedContentSettings -#else -#define MAYBE_MixedContentSettings MixedContentSettings -#endif - // This test checks the behavior of mixed content blocking for the requests // from a dedicated worker by changing the settings in WebPreferences. -IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, MAYBE_MixedContentSettings) { +// TODO(crbug.com/890372): This test is flaky. +IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, DISABLED_MixedContentSettings) { ChromeContentBrowserClientForMixedContentTest browser_client; content::ContentBrowserClient* old_browser_client = content::SetBrowserClientForTesting(&browser_client); @@ -4034,20 +4028,12 @@ content::SetBrowserClientForTesting(old_browser_client); } -// Flaky on Windows 7 (dbg) trybot, see https://crbug.com/443374. -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_MixedContentSettingsWithBlockingCSP \ - DISABLED_MixedContentSettingsWithBlockingCSP -#else -#define MAYBE_MixedContentSettingsWithBlockingCSP \ - MixedContentSettingsWithBlockingCSP -#endif - // This test checks that all mixed content requests from a dedicated worker are // blocked regardless of the settings in WebPreferences when // block-all-mixed-content CSP is set. +// TODO(crbug.com/890372): This test is flaky. IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, - MAYBE_MixedContentSettingsWithBlockingCSP) { + DISABLED_MixedContentSettingsWithBlockingCSP) { ChromeContentBrowserClientForMixedContentTest browser_client; content::ContentBrowserClient* old_browser_client = content::SetBrowserClientForTesting(&browser_client); @@ -4081,17 +4067,12 @@ content::SetBrowserClientForTesting(old_browser_client); } -// Flaky on Windows 7 bot, see https://crbug.com/874959. -#if defined(OS_WIN) -#define MAYBE_MixedContentSubFrame DISABLED_MixedContentSubFrame -#else -#define MAYBE_MixedContentSubFrame MixedContentSubFrame -#endif // This test checks that all mixed content requests from a dedicated worker // which is started from a subframe are blocked if // allow_running_insecure_content setting is false or // strict_mixed_content_checking setting is true. -IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, MAYBE_MixedContentSubFrame) { +// TODO(crbug.com/890372): This test is flaky. +IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest, DISABLED_MixedContentSubFrame) { // TODO(carlosil): Reenable tests once confirmed not flaky for committed // interstitials. if (AreCommittedInterstitialsEnabled())
diff --git a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc index 49fba81..6bcb9ff02 100644 --- a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc +++ b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
@@ -88,7 +88,7 @@ ASSERT_TRUE(ax_tree.GetRoot()); // ID's should be > 0. - ASSERT_GE(ax_tree.GetRoot()->GetUniqueId().Get(), 1); + ASSERT_GE(ax_tree.GetRoot()->GetUniqueId(), 1); // Grab the content view directly from cache to avoid walking down the tree. AXAuraObjWrapper* content = @@ -131,7 +131,7 @@ ASSERT_FALSE(textfield_->HasFocus()); ui::AXActionData action_data; action_data.action = ax::mojom::Action::kDoDefault; - action_data.target_node_id = textfield_wrapper->GetUniqueId().Get(); + action_data.target_node_id = textfield_wrapper->GetUniqueId(); textfield_wrapper->HandleAccessibleAction(action_data); ASSERT_TRUE(textfield_->HasFocus()); } @@ -147,7 +147,7 @@ ASSERT_FALSE(textfield_->HasFocus()); ui::AXActionData action_data; action_data.action = ax::mojom::Action::kFocus; - action_data.target_node_id = textfield_wrapper->GetUniqueId().Get(); + action_data.target_node_id = textfield_wrapper->GetUniqueId(); textfield_wrapper->HandleAccessibleAction(action_data); ASSERT_TRUE(textfield_->HasFocus()); } @@ -184,7 +184,7 @@ int text_field_update_index = -1; for (size_t i = 0; i < node_count; ++i) { - if (textfield_wrapper->GetUniqueId().Get() == out_update2.nodes[i].id) + if (textfield_wrapper->GetUniqueId() == out_update2.nodes[i].id) text_field_update_index = i; }
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc index ef73767a..c000c0c 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -95,7 +95,7 @@ // This helps us avoid firing accessibility events for transient changes. // because there's a chance that the underlying object being wrapped could // be deleted, pass the ID of the object rather than the object pointer. - int32_t id = obj->GetUniqueId().Get(); + int32_t id = obj->GetUniqueId(); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&AutomationManagerAura::SendEventOnObjectById, @@ -214,7 +214,7 @@ // ancestor) but we shouldn't fire the event on the node not in the tree. if (current_tree_serializer_->IsInClientTree(aura_obj)) { ui::AXEvent event; - event.id = aura_obj->GetUniqueId().Get(); + event.id = aura_obj->GetUniqueId(); event.event_type = event_type; event_bundle.events.push_back(event); }
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc index cda6bd1..b8f91a7 100644 --- a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc +++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
@@ -176,21 +176,21 @@ // Focus view1, then block until we get an accessibility event that // shows this view is focused. view1->RequestFocus(); - waiter.WaitForNodeIdToBeFocused(wrapper1->GetUniqueId().Get()); + waiter.WaitForNodeIdToBeFocused(wrapper1->GetUniqueId()); - EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper1->GetUniqueId().Get())); - EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper2->GetUniqueId().Get())); - EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper3->GetUniqueId().Get())); + EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper1->GetUniqueId())); + EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper2->GetUniqueId())); + EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper3->GetUniqueId())); // Now focus view2 and then view3. We shouldn't ever get an event // showing view2 as focused, just view3. view2->RequestFocus(); view3->RequestFocus(); - waiter.WaitForNodeIdToBeFocused(wrapper3->GetUniqueId().Get()); + waiter.WaitForNodeIdToBeFocused(wrapper3->GetUniqueId()); - EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper1->GetUniqueId().Get())); - EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper2->GetUniqueId().Get())); - EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper3->GetUniqueId().Get())); + EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper1->GetUniqueId())); + EXPECT_FALSE(waiter.WasNodeIdFocused(wrapper2->GetUniqueId())); + EXPECT_TRUE(waiter.WasNodeIdFocused(wrapper3->GetUniqueId())); cache->set_focused_widget_for_testing(nullptr);
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc index ce99b97..13a2ae1 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.cc +++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -232,11 +232,6 @@ typedef std::unique_ptr<GtkIconInfo, GtkIconInfoDeleter> ScopedGtkIconInfo; typedef std::unique_ptr<GdkPixbuf, GObjectDeleter> ScopedGdkPixbuf; -#if !GTK_CHECK_VERSION(3, 90, 0) -// Prefix for app indicator ids -const char kAppIndicatorIdPrefix[] = "chrome_app_indicator_"; -#endif - // Number of app indicators used (used as part of app-indicator id). int indicators_count; @@ -545,7 +540,8 @@ std::unique_ptr<views::StatusIconLinux> GtkUi::CreateLinuxStatusIcon( const gfx::ImageSkia& image, - const base::string16& tool_tip) const { + const base::string16& tool_tip, + const char* id_prefix) const { #if GTK_CHECK_VERSION(3, 90, 0) NOTIMPLEMENTED(); return nullptr; @@ -553,8 +549,8 @@ if (AppIndicatorIcon::CouldOpen()) { ++indicators_count; return std::unique_ptr<views::StatusIconLinux>(new AppIndicatorIcon( - base::StringPrintf("%s%d", kAppIndicatorIdPrefix, indicators_count), - image, tool_tip)); + base::StringPrintf("%s%d", id_prefix, indicators_count), image, + tool_tip)); } else { return std::unique_ptr<views::StatusIconLinux>( new GtkStatusIcon(image, tool_tip));
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.h b/chrome/browser/ui/libgtkui/gtk_ui.h index 1c626d1..2c98c19 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.h +++ b/chrome/browser/ui/libgtkui/gtk_ui.h
@@ -90,7 +90,8 @@ bool IsStatusIconSupported() const override; std::unique_ptr<views::StatusIconLinux> CreateLinuxStatusIcon( const gfx::ImageSkia& image, - const base::string16& tool_tip) const override; + const base::string16& tool_tip, + const char* id_prefix) const override; gfx::Image GetIconForContentType(const std::string& content_type, int size) const override; std::unique_ptr<views::Border> CreateNativeBorder(
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index ac5ef04..e4f7a82 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -78,6 +78,7 @@ #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/event_injector.h" #include "ui/aura/test/env_test_helper.h" #include "ui/base/class_property.h" #include "ui/base/hit_test.h" @@ -238,6 +239,15 @@ DISALLOW_COPY_AND_ASSIGN(ImmersiveModeTester); }; +// Update mouse location of aura::Env by injecting a mouse move event. +// EventInjector is used so that the Window Service side code under mash sees +// the updated mouse location as well. +void UpdateMouseLocation(aura::Window* window, const gfx::Point& location) { + ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, + ui::EventTimeForNow(), ui::EF_NONE, 0); + aura::EventInjector().Inject(window->GetHost(), &event); +} + } // namespace using views::Widget; @@ -304,7 +314,10 @@ } IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) { - aura::test::EnvTestHelper().SetAlwaysUseLastMouseLocation(true); + // Move mouse cursor beyond immersive UI to avoid affecting tests. + UpdateMouseLocation(browser()->window()->GetNativeWindow(), + gfx::Point(0, 100)); + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); content::WebContents* web_contents = browser_view->GetActiveWebContents(); BrowserNonClientFrameViewAsh* frame_view = GetFrameViewAsh(browser_view); @@ -515,9 +528,14 @@ ImmersiveModeBrowserViewTest() = default; ~ImmersiveModeBrowserViewTest() override = default; + // TopChromeMdParamTest<InProcessBrowserTest>: void PreRunTestOnMainThread() override { InProcessBrowserTest::PreRunTestOnMainThread(); - aura::test::EnvTestHelper().SetAlwaysUseLastMouseLocation(true); + + // Move mouse cursor beyond immersive UI to avoid affecting tests. + UpdateMouseLocation(browser()->window()->GetNativeWindow(), + gfx::Point(0, 100)); + BrowserView::SetDisableRevealerDelayForTesting(true); }
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc index eed6bb2..4694a9a 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
@@ -8,6 +8,13 @@ #include "ui/message_center/public/cpp/notifier_id.h" #include "ui/views/linux_ui/linux_ui.h" +namespace { + +// Prefix for app indicator ids +const char kAppIndicatorIdPrefix[] = "chrome_app_indicator_"; + +} // namespace + StatusIconLinuxWrapper::StatusIconLinuxWrapper( std::unique_ptr<views::StatusIconLinux> status_icon) : status_icon_(std::move(status_icon)), menu_model_(nullptr) { @@ -53,7 +60,8 @@ const base::string16& tool_tip) { const views::LinuxUI* linux_ui = views::LinuxUI::instance(); if (linux_ui) { - auto status_icon = linux_ui->CreateLinuxStatusIcon(image, tool_tip); + auto status_icon = + linux_ui->CreateLinuxStatusIcon(image, tool_tip, kAppIndicatorIdPrefix); if (status_icon) { return base::WrapUnique( new StatusIconLinuxWrapper(std::move(status_icon)));
diff --git a/chrome/browser/vr/browser_renderer.cc b/chrome/browser/vr/browser_renderer.cc index 6d10dc7d..8f4049a 100644 --- a/chrome/browser/vr/browser_renderer.cc +++ b/chrome/browser/vr/browser_renderer.cc
@@ -231,7 +231,7 @@ frame_buffer_dump_filepath_base_ = filepath_base; } -void BrowserRenderer::WatchElementForVisibilityChangeForTesting( +void BrowserRenderer::WatchElementForVisibilityStatusForTesting( VisibilityChangeExpectation visibility_expectation) { DCHECK(ui_visibility_state_ == nullptr) << "Attempted to watch a UI element " "for visibility changes with one " @@ -240,8 +240,7 @@ ui_visibility_state_->timeout_ms = base::TimeDelta::FromMilliseconds(visibility_expectation.timeout_ms); ui_visibility_state_->element_to_watch = visibility_expectation.element_name; - ui_visibility_state_->initially_visible = ui_->GetElementVisibilityForTesting( - ui_visibility_state_->element_to_watch); + ui_visibility_state_->expected_visibile = visibility_expectation.visibility; } void BrowserRenderer::AcceptDoffPromptForTesting() { @@ -405,13 +404,13 @@ base::TimeDelta time_since_start = current_time - ui_visibility_state_->start_time; if (ui_->GetElementVisibilityForTesting( - ui_visibility_state_->element_to_watch) != - ui_visibility_state_->initially_visible) { + ui_visibility_state_->element_to_watch) == + ui_visibility_state_->expected_visibile) { ReportElementVisibilityResultForTesting( - UiTestOperationResult::kVisibilityChange); + UiTestOperationResult::kVisibilityMatch); } else if (time_since_start > ui_visibility_state_->timeout_ms) { ReportElementVisibilityResultForTesting( - UiTestOperationResult::kTimeoutNoChange); + UiTestOperationResult::kTimeoutNoVisibilityMatch); } } @@ -419,7 +418,7 @@ UiTestOperationResult result) { ui_visibility_state_ = nullptr; browser_->ReportUiOperationResultForTesting( - UiTestOperationType::kElementVisibilityChange, result); + UiTestOperationType::kElementVisibilityStatus, result); } } // namespace vr
diff --git a/chrome/browser/vr/browser_renderer.h b/chrome/browser/vr/browser_renderer.h index bd5d1f8..30f60d4 100644 --- a/chrome/browser/vr/browser_renderer.h +++ b/chrome/browser/vr/browser_renderer.h
@@ -74,7 +74,7 @@ void SetUiExpectingActivityForTesting( UiTestActivityExpectation ui_expectation); void SaveNextFrameBufferToDiskForTesting(std::string filepath_base); - void WatchElementForVisibilityChangeForTesting( + void WatchElementForVisibilityStatusForTesting( VisibilityChangeExpectation visibility_expectation); void AcceptDoffPromptForTesting(); void ConnectPresentingService(
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index c9e610f..9d74615f 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -77,6 +77,12 @@ return kOmniboxTextField; case UserFriendlyElementName::kOmniboxCloseButton: return kOmniboxCloseButton; + case UserFriendlyElementName::kAppButtonExitToast: + return kWebVrExclusiveScreenToast; + case UserFriendlyElementName::kWebXrAudioIndicator: + return kWebVrAudioCaptureIndicator; + case UserFriendlyElementName::kWebXrHostedContent: + return kWebVrHostedUiContent; default: NOTREACHED(); return kNone;
diff --git a/chrome/browser/vr/ui_test_input.h b/chrome/browser/vr/ui_test_input.h index c6ef1ce7..552e2a9 100644 --- a/chrome/browser/vr/ui_test_input.h +++ b/chrome/browser/vr/ui_test_input.h
@@ -30,6 +30,12 @@ kOmniboxTextField, // The Omnibox's text input field that shows up when the // URL bar is clicked. kOmniboxCloseButton, // The button the exits the omnibox's text input mode. + kAppButtonExitToast, // The "Press app button to exit" toast when entring + // an immersive session. + kWebXrAudioIndicator, // Toast in WebXR indicating the microphone permission + // is in use. + kWebXrHostedContent, // Hosted content in a WebXR immersive session, e.g. + // permission prompts. }; // These are the types of actions that Java can request callbacks for once @@ -38,7 +44,8 @@ enum class UiTestOperationType : int { kUiActivityResult = 0, // Result after being told to wait for quiescence kFrameBufferDumped, // Signal that the frame buffer was dumped to disk - kElementVisibilityChange, // Signal that a watched element changed visibility + kElementVisibilityStatus, // Signal that a watched element matches the + // desired visibility. kNumUiTestOperationTypes, // Must be last }; @@ -49,10 +56,10 @@ kQuiescent, // The UI reached quiescence (kUiActivityResult) kTimeoutNoStart, // Timed out, UI activity never started (kUiActivityResult) kTimeoutNoEnd, // Timed out, UI activity never finished (kUiActivityResult) - kVisibilityChange, // The watched element's visibility changed - // (kElementVisibilityChange) - kTimeoutNoChange, // Timed out, visibility never changed - // (kElementVisibilityChange) + kVisibilityMatch, // The watched element's visibility matches the expectation + // (kElementVisibilityStatus) + kTimeoutNoVisibilityMatch, // Timed out, visibility doesn't match expectation + // (kElementVisibilityStatus) }; // These are used to specify what type of action should be performed on a UI @@ -100,6 +107,7 @@ struct VisibilityChangeExpectation { UserFriendlyElementName element_name; int timeout_ms; + bool visibility; }; // Holds all the information necessary to keep track of and report whether the @@ -119,8 +127,8 @@ struct UiVisibilityState { // The UI element being watched. UserFriendlyElementName element_to_watch = UserFriendlyElementName::kUrl; - // The initial visibility state of the element. - bool initially_visible = false; + // The desired visibility state of the element. + bool expected_visibile = false; // How long to wait for a visibility change before timing out. base::TimeDelta timeout_ms = base::TimeDelta::Min(); // The point in time that we started watching for visibility changes.
diff --git a/chrome/renderer/resources/extensions/automation_custom_bindings.js b/chrome/renderer/resources/extensions/automation_custom_bindings.js index 50b5c89..129b3e4 100644 --- a/chrome/renderer/resources/extensions/automation_custom_bindings.js +++ b/chrome/renderer/resources/extensions/automation_custom_bindings.js
@@ -265,6 +265,9 @@ // root node when nothing has focus, we need to treat those as focus // events but otherwise not handle blur events specially. var node = privates(targetTree).impl.get(eventParams.targetID); + if (!node) + return; + if (node == node.root) automationUtil.updateFocusedNodeOnBlur(); } else if (eventParams.eventType == 'mediaStartedPlaying' ||
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc index 0e4f47d..736add8 100644 --- a/chrome/test/chromedriver/element_commands.cc +++ b/chrome/test/chromedriver/element_commands.cc
@@ -603,20 +603,29 @@ } Status ExecuteGetElementValueOfCSSProperty( - Session* session, - WebView* web_view, - const std::string& element_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - std::string property_name; - if (!params.GetString("propertyName", &property_name)) - return Status(kUnknownError, "missing 'propertyName'"); - std::string property_value; - Status status = GetElementEffectiveStyle( - session, web_view, element_id, property_name, &property_value); + Session* session, + WebView* web_view, + const std::string& element_id, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { + bool is_xml = false; + Status status = IsDocumentTypeXml(session, web_view, &is_xml); if (status.IsError()) return status; - value->reset(new base::Value(property_value)); + + if (is_xml) { + value->reset(new base::Value("")); + } else { + std::string property_name; + if (!params.GetString("propertyName", &property_name)) + return Status(kUnknownError, "missing 'propertyName'"); + std::string property_value; + status = GetElementEffectiveStyle( + session, web_view, element_id, property_name, &property_value); + if (status.IsError()) + return status; + value->reset(new base::Value(property_value)); + } return Status(kOk); }
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc index a5e0fe5d..7794edb 100644 --- a/chrome/test/chromedriver/element_util.cc +++ b/chrome/test/chromedriver/element_util.cc
@@ -358,6 +358,25 @@ return Status(kOk); } +Status IsDocumentTypeXml( + Session* session, + WebView* web_view, + bool* is_xml_document) { + + std::unique_ptr<base::Value> contentType; + Status status = web_view->EvaluateScript( + session->GetCurrentFrameId(), + "document.contentType", &contentType); + if (status.IsError()) + return status; + if (base::LowerCaseEqualsASCII(contentType->GetString(), + "text/xml")) + *is_xml_document = true; + else + *is_xml_document = false; + return Status(kOk); +} + Status GetElementAttribute(Session* session, WebView* web_view, const std::string& element_id,
diff --git a/chrome/test/chromedriver/element_util.h b/chrome/test/chromedriver/element_util.h index 3cf3548..c0e2558 100644 --- a/chrome/test/chromedriver/element_util.h +++ b/chrome/test/chromedriver/element_util.h
@@ -45,6 +45,11 @@ const std::string& element_id, bool* is_focused); +Status IsDocumentTypeXml( + Session* session, + WebView* web_view, + bool* is_xml_document); + Status GetElementAttribute(Session* session, WebView* web_view, const std::string& element_id,
diff --git a/chrome/test/data/extensions/api_test/webstore_private/theme.html b/chrome/test/data/extensions/api_test/webstore_private/theme.html index c0d59e0..9200510b 100644 --- a/chrome/test/data/extensions/api_test/webstore_private/theme.html +++ b/chrome/test/data/extensions/api_test/webstore_private/theme.html
@@ -6,7 +6,7 @@ <script src="common.js"></script> <script> -var themeId = 'iamefpfkojoapidjnbafmgkgncegbkad'; +var themeId = 'idlfhncioikpdnlhnmcjogambnefbbfp'; runTests([ function installTheme() {
diff --git a/chrome/test/data/extensions/app_update/v1.crx b/chrome/test/data/extensions/app_update/v1.crx index 86b6f7f..68f58de9 100644 --- a/chrome/test/data/extensions/app_update/v1.crx +++ b/chrome/test/data/extensions/app_update/v1.crx Binary files differ
diff --git a/chrome/test/data/extensions/app_update/v2.crx b/chrome/test/data/extensions/app_update/v2.crx index 49205ca..8a59727 100644 --- a/chrome/test/data/extensions/app_update/v2.crx +++ b/chrome/test/data/extensions/app_update/v2.crx Binary files differ
diff --git a/chrome/test/data/extensions/blocked_file_types.crx b/chrome/test/data/extensions/blocked_file_types.crx index 331d7c8..7ff9dde 100644 --- a/chrome/test/data/extensions/blocked_file_types.crx +++ b/chrome/test/data/extensions/blocked_file_types.crx Binary files differ
diff --git a/chrome/test/data/extensions/good.crx b/chrome/test/data/extensions/good.crx index fe592fc..83038c19 100644 --- a/chrome/test/data/extensions/good.crx +++ b/chrome/test/data/extensions/good.crx Binary files differ
diff --git a/chrome/test/data/extensions/good2.crx b/chrome/test/data/extensions/good2.crx index 21471425..b40b2444 100644 --- a/chrome/test/data/extensions/good2.crx +++ b/chrome/test/data/extensions/good2.crx Binary files differ
diff --git a/chrome/test/data/extensions/good2048.crx b/chrome/test/data/extensions/good2048.crx index 4bd64f7..db01d6e 100644 --- a/chrome/test/data/extensions/good2048.crx +++ b/chrome/test/data/extensions/good2048.crx Binary files differ
diff --git a/chrome/test/data/extensions/good2048.pem b/chrome/test/data/extensions/good2048.pem new file mode 100644 index 0000000..05fba5c --- /dev/null +++ b/chrome/test/data/extensions/good2048.pem
@@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbgQq8G6sXT7ex +nY9wIcODu1uq27JXsMaV8gaaNjvI5a/atxYzzAB7O8hemwSEYL5ZgAjhfYtuFbaf +soHIx934UNqi4Bbcg7Qxcbg9AHmMjN+U/gVzBmN8VSHNMF4UvII2LFlFuuWcHw8o +71dDI3b2Bjhdhl8n2KVJtdoB42yQ+wHcg+XvwUJXnoLySabX8hLoHTgkw6oUJCDo +6Sk1OCE68Zv/p+/2QGkmpHtSjzEvvK3inDQhnbhXJ3PycH4tvINu39ebhIFoe2kV +3KpiHzoIjdVSXuCEukq1HQeJeu28Q//R6J+PBsTHKSQPTyNGAbOt8FuRQsy0QiCB +DCFL/4v/AgMBAAECggEBAKHsMlgLbQ24P8Dlgv9r2MefeYKzqH7pp8TLEjXGVhnf +3fbQ4q75CU3fDvNDFXT1zNVHDsYQj794gwyRaQ4M6mCYfIB0IEkxWsaypf9SD1gw +P2qwbKKqjs8UGeg8itpvKPr/gidfNKwTeWJwFIYxbjsU4ZWUXzOMrHmQja6g7uCO ++9WdTxLBXmyb7pKJIlKAKg3Dlpj7kTF3hFpLLYhC6Ruv+ItPrqltMWyt5rY0Ay09 +LV8/Vs1ikWN9fKhlGJpFX8sbFQmuJjT+uv1yguRzlFOQS1UQCVcDcOlj0AkHMtqV +icva88uI3DGtSN1Sy5q14zZOhQK2NrGu0zTHrBm/CAkCgYEA7ikImAjpVxSUek0Y +sUdvbL0LkPm4o94/OFDvAWrGO7ue43V80j4NlxlJUWe9g6nC5oRf9tFPsbvJnRBE +9ANMF1khEPqVdOyb80Elv+fC/eb9nOY/nGMBolV/n2kSW+ZVKMeD/ynDakIuZEXn +AIn8lKd4DGE0f++Yq01NOguu9vMCgYEA6/JBoT0IQjMlbN3PU2NZhIyGassv6QMf +53d+PzhV2yWwipHoroYEFywLuNNXXZcA4GLSknJ/7KN5apiDnbK2kCSppEYwDIEZ +gy9FiXq2a3xpPLWqjmG8rrkyTAfdF8EZatMFj/Y1CAQoqV+5ux6BEsgVHH1Sw/9E +bLHZFs5NMcUCgYEAr52mbqWzmrjcO8r5+E+axG4qRz89feh2acqUU1Eu2AEjyspp +voZvcwn8XIDI6HuX8m+Oa+wwffjhVGYY0m5T/6uDjIebCdsnrBpQAdCeoqdgQAAw +y9rd65xsPVo3ZXjVNvrYRKHBLWub1ekNzAH0NJHBHi/XjLdatoaL+c9/ty0CgYAD +IsIaiXwdnR5nNv91ZUGgUFnM+4xUdXUsF1t3LaF+ex7AiLXl8+QEBtLVDwH/PW2G +jemshpcKpxWLBCHjq6dffQ1AIKqsz95t7ufmrtnTzeB8LRHqOIRQcien+QbINQnI +cKuHQUdtJtj/f0UxpnMis8QMD+JUtoTLSQXQlsdR3QKBgA9HpCXy/5yDnyXwkSpn +kKrR0c2wWG+dQYz+ggGOAQrWWcEGCkNCVJbeJ59zBOWfSvpLDG1qpJHOfx5sr5Xi +pcrjruQpkaQdn/i51LaDvOh8Cc9E9c+kC9TtwelsXMbx16FvbuPR5kPHLXuLMYpz +f58gNCOAOtu9/gw9bTIHzYNI +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/good_v1.crx b/chrome/test/data/extensions/good_v1.crx index bcd79e7..9cf3d5d 100644 --- a/chrome/test/data/extensions/good_v1.crx +++ b/chrome/test/data/extensions/good_v1.crx Binary files differ
diff --git a/chrome/test/data/extensions/hosted_app.crx b/chrome/test/data/extensions/hosted_app.crx index 3405cc6..0778bdb 100644 --- a/chrome/test/data/extensions/hosted_app.crx +++ b/chrome/test/data/extensions/hosted_app.crx Binary files differ
diff --git a/chrome/test/data/extensions/hosted_app.pem b/chrome/test/data/extensions/hosted_app.pem index ae52b2c..b0c676c 100644 --- a/chrome/test/data/extensions/hosted_app.pem +++ b/chrome/test/data/extensions/hosted_app.pem
@@ -1,16 +1,16 @@ -----BEGIN PRIVATE KEY----- -MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAK7M0HNplXttVzfXO -+144ovZo7AD32InVr7fVKEBuWFSc2Pp3crY8wy+/uBvFAzAJqz34/57NL3osY2oSf -Yk7iAEXb3bdQAmkDh3QON9SanWfZrCybudA0mp0EuE2mP4isaAPkJigF6hOTX//jn -fjsW4BzM2MXosaqYajHmUW5btAgMBAAECgYEAoJ5avHI8hRnHluwTiPYXVWI64rXs -QYjcUK9uWDP5X9Afb6OpxYbsbr3h/eCTj9PQtgdiXKhhok97Nyt4KtFsbEDwwWGZG -FSG2p4uP0Mfp2s70CgFxZf9zspORY/oe3k+LZecbwotRABI2Rl1dNErsWOTNZ6CNL -bUO9GzuMERh5ECQQDmMNSyFPw/bukoWLtbMIHrNtf0jaFTIzlZYirFn0hD8CwzfvL -eLCVRZY7F7WE+30ryUHLp1CsK3qFXHyEhasQ/AkEAwmYaeywcIIpH9T1Kj6UKJjMb -R57SqK1G6iCw2W0EvgjHVi0UR59OQSpaNFdr5BJH4aqa4anDiceFv/oqMaJp0wJBA -KuKgkb/uodvGNQXY+/t8zOdWEwH68wv+MHylRtWuxzd86KgnU8SKPFCtKYtY4XeE1 -UGvMwib70W8bciHKdxkDMCQQCliYqdPneJIheadqHKZjCZTMW7HDyolD0h28qcq1/ -xbspH0MVHJBngFe+QSK1AHm0FdmDDLuuqpLN5Qc6yS2ovAkEAzy9bgr3bcYFmQfaE -3520gtCU06p68dSqGKQKH5G7Cdko27Ij+N0XDxWNhyzaAR5xWlXVspV+RdOQFTpMH -qnd+w== +MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAK7M0HNplXttVzfX +O+144ovZo7AD32InVr7fVKEBuWFSc2Pp3crY8wy+/uBvFAzAJqz34/57NL3osY2o +SfYk7iAEXb3bdQAmkDh3QON9SanWfZrCybudA0mp0EuE2mP4isaAPkJigF6hOTX/ +/jnfjsW4BzM2MXosaqYajHmUW5btAgMBAAECgYEAoJ5avHI8hRnHluwTiPYXVWI6 +4rXsQYjcUK9uWDP5X9Afb6OpxYbsbr3h/eCTj9PQtgdiXKhhok97Nyt4KtFsbEDw +wWGZGFSG2p4uP0Mfp2s70CgFxZf9zspORY/oe3k+LZecbwotRABI2Rl1dNErsWOT +NZ6CNLbUO9GzuMERh5ECQQDmMNSyFPw/bukoWLtbMIHrNtf0jaFTIzlZYirFn0hD +8CwzfvLeLCVRZY7F7WE+30ryUHLp1CsK3qFXHyEhasQ/AkEAwmYaeywcIIpH9T1K +j6UKJjMbR57SqK1G6iCw2W0EvgjHVi0UR59OQSpaNFdr5BJH4aqa4anDiceFv/oq +MaJp0wJBAKuKgkb/uodvGNQXY+/t8zOdWEwH68wv+MHylRtWuxzd86KgnU8SKPFC +tKYtY4XeE1UGvMwib70W8bciHKdxkDMCQQCliYqdPneJIheadqHKZjCZTMW7HDyo +lD0h28qcq1/xbspH0MVHJBngFe+QSK1AHm0FdmDDLuuqpLN5Qc6yS2ovAkEAzy9b +gr3bcYFmQfaE3520gtCU06p68dSqGKQKH5G7Cdko27Ij+N0XDxWNhyzaAR5xWlXV +spV+RdOQFTpMHqnd+w== -----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/minimal_platform_app.crx b/chrome/test/data/extensions/minimal_platform_app.crx index 68103a6..6d1f08ed 100644 --- a/chrome/test/data/extensions/minimal_platform_app.crx +++ b/chrome/test/data/extensions/minimal_platform_app.crx Binary files differ
diff --git a/chrome/test/data/extensions/sync_datatypes/v1.crx b/chrome/test/data/extensions/sync_datatypes/v1.crx index 2412eb87..d60449e 100644 --- a/chrome/test/data/extensions/sync_datatypes/v1.crx +++ b/chrome/test/data/extensions/sync_datatypes/v1.crx Binary files differ
diff --git a/chrome/test/data/extensions/sync_datatypes/v2.crx b/chrome/test/data/extensions/sync_datatypes/v2.crx index 97375e7..9e3a32b8 100644 --- a/chrome/test/data/extensions/sync_datatypes/v2.crx +++ b/chrome/test/data/extensions/sync_datatypes/v2.crx Binary files differ
diff --git a/chrome/test/data/extensions/theme.crx b/chrome/test/data/extensions/theme.crx index e80391dc..51155ef8c 100644 --- a/chrome/test/data/extensions/theme.crx +++ b/chrome/test/data/extensions/theme.crx Binary files differ
diff --git a/chrome/test/data/extensions/theme.pem b/chrome/test/data/extensions/theme.pem new file mode 100644 index 0000000..478b3ae --- /dev/null +++ b/chrome/test/data/extensions/theme.pem
@@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCyEXc9ctGVfVeb +kmUC5S3JFDyPfcox3e2RLlhxMrnKeuRk92EZPrg8Y7VC9hs3ROj+AHpbHf9FMMtr +AczJ3ytW+qtfUX6MolnOHsXuaIuPeME1Efasb4qIZp6/g0lqNfV4SqG4BBXaN/hB +hWN28mDyJprZ4KSK4HBjNgnuzyDnobeNGJYZyJWKo6IWMTkVL/PfTrz1q3FOKt6h +ZgmRkA5qN6gJ+FI5wJeSSvRawbVNFp0Rbh2n6Nnxy3h+SWfFpIcS83u0W1CTKRRu +DcqR8UR5PGEJrD9LAWgvXAvZcdbMNacRSBVz/J/bHsAG+cxkVygEpSgFTy4EVa2H +/O2q9Or90DSmB/jGElNipC7uGSJy92krKQ5iQLlPsfEewyXk2X6+DML9k/7Et4H3 +CPqWz+QgSSQago4t9KEKV/KtIZ0Vo4lsNBTBDJRCzqkdKkFyNYzD33uVgYAyOTY6 +yc2h7HqOQnDslAKc0xA0QCM9JFviCMJJrEve2XQN5QQaingm5DRgqh29J4pM/sFJ +8HZcTw74v3pzL6dW5yeWAK9GYUsDlbX1cI5vuJcg/ke5t/KxocwEEmUrJkCopmWS +xcy9050gpgEk2t2bDtXEqPvClgnEazEo6H+gZHRUT6cZGQbBBkzWChjy6njC2zLY +VZjudjEDW11s0WO/FNMVkg6CqEWw/wIDAQABAoICAQCi66wHgtgTSF0xr93PqlQb +1/IY72Rh/8VuwdKVr22hvpLddiFW8bWrOycLHxWDmf769wD8ARQgACb9vuXaBeAn +cq39RhjdH2W/WxSJrwmRuVA8+DSTTHKZnhq86qfvD3OKHe6c6M/9mpv/hsWcfOMK +axvfINQrZHIvs6+e2dAnXiUMaWRcLtPzxwdz+pFZu0gMFoR42eWPOVX8odk7X2xw +7n9Gr/a7dGS5qu6rYvQ4leobmn5ztG5D9oBGO29Au+oCAtg6ChpMqpdQojmnEfIu +Ynn+WaSHQcBLJJKK3sdCjAxRmXxXZNn1p8rWFxNU8xFgPqPBR9K4kJN3ComBkxi0 +nXnGGXm7LUBzEgk4ArRsBPqktdMNThe3WfKv2oLxrkkaLTHlZTPhFjLFAmecUCIo +UdHYOj5Q+3wLbjUMsrun7y7T2+rfroAj57NDh3VzVDrsJBvhS1xDsM213dMOZaGc +f2ANiGl3xoYGqZeC9k40NBOqt//KNgNC8IZeQdEFJs4WwM49jyu53+VzvfYKWgPz +sSpmI1TYW+ac84yOfCkW6rBEGXiDiFX0K15Bi7ItwgnxST25X2LqwNHnVcwYvB6K +ZBpi5aGtr+j/H8aQMU6ycGZvtj51pF8yhVXALtvld2srQijKYmp+fYSt9dXI8SrG +sif4jKocztvj+lyu97RccQKCAQEA5NcyGTXMpou22iAIUVi195IEl0KcXkbmVxCa +b04pxWzgzgwuRrZ1xV2vg0mnyoE5Rrhva6oGhQGfvPoaCyEvxWTFL0QRiNOOkvBJ +3uO/BqI6aKoA7+aW1T53nvg+ZncnTLZZ+ee/afH509hlq1uv8bflp2g5dbIuouia +Zl83O1vKuJllld8jstE1F9vRePVP+W+vmuNk/d9k1GFgVAqoGPnEc7cEDXBM0OJW +chG05p+Yr9UDQPzWLAMtA8s0WQPkmTVUeoWNtLEhjkn0CbXjbjofLYRYdKDmLQr7 +2CQ8Lwi/PR2eSc5OgxH/Wmu5KF0wdVTF5/1r04p/0yN0zgUwCwKCAQEAxzOqg/fi +1yOfldnhXcCJ+XNcFp37wlY+nrnHCRu09ZvW/BySbKyI7p/WnjQGobqKxil3nhUy +AgGq9fUweY625q28yhdUDOK826xYUyy+dK01zBHClCetuibig9iSoPhV3qEQRe8u +DO9G83OLIxiWs2cO6jZIeNDr/YtWb9+Pa47l9MZG07ozvbpbcmm3arc51WCSoTGR +D8meYgPb6/gdchluWSJV0HWqNCpbBlWwRArSiVd9eYE5QpBV02kO9tCSbNYqzTGA +rZkMxsTDUfy3arfeMD5NVGrPS5YJaCVILRGulpb7IL5CrtExH9fRRvJIN4ZSelm9 +yergkdbfE17XXQKCAQEA297Hi+FdGEf1D+7nDwGlFJF/R7YAd7S3a7/QIlF/YOkT +teWOMPLuhQtWr1X9mVw/o+thYpiiWvkMeY3zp+3i8E26B4fnMQfTXOryju1ThRQp ++pYdAGMVWR4D4QGzMtAZOmOaX7qC91A/MYQha1tU2XJPfWFuk973YB8M+n9Rmf6/ +8E2yhSU4L39C/AGAai+I/6iHmNITHrmdL1HAM/9pM1YHowadJixYIfrWBBNvNIbz +NT39Oluzi+YhQhvj2AMdiPbsjCv10z69dvEnQI06T5YYjqsyMhzGC1EaWLm3+Zj1 +5cqnY1KNrPGF32LRLC8deB5TaGrdRwszdbIDcE8bsQKCAQB8XliGfjylH3uiXl7j +XrOGB60l/crSYXBFPy3yFNddRMfrrZcJvIrdmPOw4ECHtuSvpfIlw4vuTsZDO6rh +KeYtjalB72Ctjt5ktGyMuXHLfN0KpMf8Ie3IPEDOGmgpkgJiteJoF1WEA9wjYS8s +YUytg5l/RxbmP2IncVgtDsIHYDdYJHbR9/4X5YL0ouY9/VlhTCMf+sdbuQBmp4wl +/km8E/6eLd6wANacLRmZkeQ0ByG9V99h/fkXAvBixsPt+viAdRJR/Ccfu1+LtgtQ +Y9zMBzH0ouE65Fi6E1maKTSv1stO/8KYhdEyPi9SdzcU+W13JSjXdLIWn8tHooSy +HlONAoIBAFNMnZdFnacmy3Znbg3tp9Y5xNrQzjmPFgID6aimfM5BWKYdn5/bEoJd +MQ3nCCKHif/dmv2EUwzDtxGCo5awrA0KdOIIBV6VyVrNlkZ8z9fPlCoMFGHPu3Hc +qzIxSNVd75SyIoTjzEd/4FvfSaLOJx1A95awJ095B7UyPy5qWEcD7Rg4IQ65vx7E +ppZ2FLxKWggrEY9h8jVERY+M8sc5dsubsttnmnXrn1TVEasHWwXi0CNkP+u7PHZS +2DA8+3H9ShqlAix09JrkS8RxSaD1tk6AqjyweXzG+TfZjK9HYT6OnjUP7IQP/PZ9 +VEq7aQWYaYOoCQ9aIvfvTcRnOtP+iYo= +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/theme2.crx b/chrome/test/data/extensions/theme2.crx index 313fc8d..f22e798 100644 --- a/chrome/test/data/extensions/theme2.crx +++ b/chrome/test/data/extensions/theme2.crx Binary files differ
diff --git a/chrome/test/data/extensions/theme2.pem b/chrome/test/data/extensions/theme2.pem new file mode 100644 index 0000000..210f872 --- /dev/null +++ b/chrome/test/data/extensions/theme2.pem
@@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDThI/R4dCzUD0o +RFzmKK0lmvsa+Thinlo+3FyhZvIkytO9RniPNM9/OvzKHu7rbbhmPooVHFYsw9sv +RefUkqtxKHNF1BYcM39l0sUh+65Q9rIjSPGVAumXt5RrGRbzFwl+7hTbJ0hoSvbl +8OhIm2NylpCVvQEspr5UvfZXxN61+F4u/wHhO+bRwXsiyv3KAzjbj67O2QZcolmd +0kI9babhSUsG2R5Z9B/eu648j2Np971k86zrlF9ZGQtMl/GxjTP/lslxcw1EA6sJ +P7H0SxqZq+M80KfQvDIwTzVa3Ts891K2tWic90NVSzlE7KC152P29E++b200WbmH +GCws1kilMvvaOG6H2liAYOJsoQ0Ga3FK2AZivuC0gAYuB4739jW8Wx6Fu6aTF7BU +Al0mPJNsE0p2A52u/0vrFhk1DwUAsXTIIva8P/BAWH0yZAps+nNP25hULtRRfhJG +jqP8OW4UKxH3BHl/ehMSGPw5O1nOYOC0u3S8cWRGe6POqIQYaMw5SPbTqKVAFc+a +h06f5R+Cvg+sTIWgrUvxqe6AeUltsDKbqpvC4Y3vVv91RmI/5TPb2LfmxO7+tin4 +ovfKzCqGS8IrkRMYWEwRMv5ACFXRgRWqkZCRWxOah528IHTw7HJ5ljVPTqatOjrl +7H3KCrVxqoFyV3dLfx5jG0gqqSqD3QIDAQABAoICAAYqGN7vC9wN/JpN079JdDJi +X+sbVE9behnW5kQ18dyspJshkKXrzhhRKcjiOehWnEcuj2uqFcDcPGkWSnlhhOmZ +WjKwyawsvAvFpsUkxqHJbsukdpX3LcOkMAknBAo1o6s1WRpB/NQ9SxDMgpiLHsza +IoCar4wTl/x0RNet/yeig2wvNmjQDBwU3XfYHqliiqerelbA8HSGrsHwvMl5hqGO +N0eN0FqiyML/CUbujuEpvTVR/Loo6tZ36mJjE0IvcVKDnH9X8Q0IZlWwq4kJH09X +ORouopVsxrGtvUpWpEFUm+6DPvdEJYw40wR1OQHUKo+p8yEDslUSQFv1kmQEIr3Q +Mpzeiskj09n2mUoAai6HFz9C1l7B7nvn6ZB/8nBum4CjP9S33SRkhMnxOabWH0rY +dZJzq++CEYHnR1KKS1cQ0acyAvdfXVrnj2ow6/Lar8Fpamnn61Rj4XpdEHsOede4 +rIg/dDikriItVv+of+NWY6eQj9u6SCTnUSxg2qksG0NJYq3VXagDhxl/jGGwKPxk +A9JXOBgjB4/IbDgJu6h/v3PDGFhk5MbkQ0LuIsTA8oIo2p62c+1jqAS2oiYfkR39 +sA2hbWAps5XOAV9rCcVpArxhBmz+cHkI38aF48OllmFhG4ncVKASuBDLWYmr27F/ +EDr+j031hd8vqOHVaxvpAoIBAQD6uB92HbO/XsaiL6U6J9NGmVKAANab/HcdBqUq +jas3Q5N/AO++Zv3QBTlP1rvOEdi59fBS7ErAJpiYYALjbFr5SKQHx4nZSWHzdqnT +jSuiAqcAberK86wDWMcUp07r1MDuHWSaAEj8/B2twxuY784Yd/mhhpmQR8cYuBvl +C6Zas4+J1Uc0rMxGSomua1+GjegJE5iGR7NDAF1zDA91R2zGTN2mdsl48NadK1Zm +eqmzdC6v3b3wXmvKuJ0RhD97XlTaSKDPbS/IMqrXkZqDNtrpokyGy/7pxHfGfE7Q +SoPOqF5VlFEowSfpKQ8IpSW6fz+urRTdV+FHFp1TqbShCmXXAoIBAQDX+RCnBQJl +5nP8/ThLy+AkVnLWVCTkRDpiiHWg1Ulji5e8sH0ZrobZmrDPh79wGOa/8TeEaR/j +3koTZ/9KK+ZNHnfJZ033k4g5Sdm+Co3tIhqgNxn/uXe/GSnkS3iidE5X/ucgKD6t +gULDhrhfuix53iYHgt9PCMUnqyLPZN+XBKPDKBY7NadjV1uMxiKKtXNvhyd4tqRZ ++9r8LbSS7RBF2XofePJF4Gi8wbuBDP8Lg8ACairUvzztZgyrmx23TKeNFE4+bjTR +ARKCIr0N8RB9KTIcnsXLcyBt7CnOYoNz1YDqucr3MEGVrNhPBuE+ms4ptHU6jUBK +SAM6m9ksuUVrAoIBAFKjF3OWDKXZ9jyE2b/WWpPde0zHefUF/LirdQsWkMVxV483 +3s1yItxKrH49N7+PMFDy2Bhs26KD1i37D1ioYT/jCnWp9iyRPGDDzuv0jtoiZ6sD +j6z/LcYYn92V27Rtdn3FYGBGEciYzKt2MIVzHQoBmVz9AWaF0gC6xi7zbQxePMRg +cMzS262bac/8ggrWgRFkzRQNU++UkjiWVA4C0b52nWP9qSBcuVAqdZrneUG13KGI +w88TQBIcUWDxpv7hs7QS1jYoNeSVlqvgyP3Quczh+rk/SbEBWb0pQczzkoguBJHO +hgWZzK7UIqllzY6v3GyVjdf63DzTHl3yBKBDzhcCggEAOIUe3YbLFN3Vluyx0ew9 +8WSKUxrcOLy+RtENb5TBywJaKHBLnO/2rHX2NamB6RUrNiorbESSqvCelCuQPNn2 +QFJr6NJXLiZ27P8ts7VRZTCapTkmXa0s8F7mfq9dl642XoL/+4Nsu71rOn5EPBEd +2JrRev+97xINfo8j4gC1HvGA5e7UupQVBUN0WwfzPDe2SQamxsmNg1sM+RgA/L57 +lrwOYLQnOzA6WMOejWxYRqwpELi2Es0lZb9iK3rBsRmnc51PyLjQq63LKTFsJnzi +4s5oJeNLQi4T25CFdFSFsEe8oDEVM9F2KHR+e1gClH6w22s1jqgungHwjmMA19p4 +lwKCAQEAqTD/h1DFPjAFel4OD2y4/1xPQGrwvbd9BS2Z07HMIGC1nW93hC7f2u87 +p8FlTySDA0zmKl5iI70kRzbChg/ZtT+Fgu11HfEABxGaEPu+a/PG8feWET0akIYA +zoNjPcfeXYpg29dpp5EwkvgMFu8nEVz/NMxci6L7f5QX44bGmQc4PRrQIgj6ikEH ++ZCboVb17Erw8krlMaQLapuQnkbVjZivorVxzZQ9Stvnoedtw7lnGPR+hsFa+JPM +/LUHdkp3S3uevtTggIRWzoh4NeH6DY6PEyxbNo93IawtY8RX6O3FqzmpWkQe5sAu +grY12sygJcDUKdWp4cj2UsmmlFXhZQ== +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/theme_missing_image.crx b/chrome/test/data/extensions/theme_missing_image.crx index f8ee133d..757a094 100644 --- a/chrome/test/data/extensions/theme_missing_image.crx +++ b/chrome/test/data/extensions/theme_missing_image.crx Binary files differ
diff --git a/chrome/test/data/extensions/theme_with_extension.crx b/chrome/test/data/extensions/theme_with_extension.crx index 77e395f..144d1e90 100644 --- a/chrome/test/data/extensions/theme_with_extension.crx +++ b/chrome/test/data/extensions/theme_with_extension.crx Binary files differ
diff --git a/chrome/test/data/extensions/theme_with_extension.pem b/chrome/test/data/extensions/theme_with_extension.pem new file mode 100644 index 0000000..61db435 --- /dev/null +++ b/chrome/test/data/extensions/theme_with_extension.pem
@@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCvyOQR4X7vopiy +Zez1RoTpsDvksehqsHC4tfBEQZ6dxsE2cb3M+Aiwa2ecbwALXwDkGQbEy7bNQpjy +uUSntJgWQkTCxNsH4ShPLg1RUrFpxpzUFFiR84JBTufXcR0g3YGfCaz/lM+rW2pn +y6p28wtlhnz5LsZU2fVjsuob/GalWxewGaco1udr5gSzfUnva2WNAiPPcROGlut6 +POMRhEqjaKe/ty6R17+RgtQSgdrJDAZ2uz+6Cla9lbcoCMg10NKsA1gu65kBS5mA +ayIOblip/Ktn//Z5+zMijLegqo7DJ8C3CmD2td3cAyycRiHz/eB8h88QTXJ0hffE +7/16+TuWgQJduOHPyv9GJqZqaryr7RdfIFb6kSbhKBNdoP8E3B2PmZ8Chjl/iiYv +rgebjhJGltMmMxWn1z3RwoVa3iivANb+MvT7Le3QN1ILg+Tb0X3pnrKR2jv/Ci4D +wTLpdFKTm4NbPg2/Lh+rbijSTdtDRIp9XdqZnuh81KA0mRKX6vi8th12yfCqD5QB +02I4bA3XLbD6QL1Rd6X3Mnft8jBxK02nflzSPMPHetXtkPsjctl14dRJddWmq/Dc +WLziObgDpL7n1KbkCq3/MGlkgodViUlCiea8Mnm0acC9nXrNv/utI8WvTO6TD84a +HqzWtap0jkCma1oP5KGdjZTYLsxqywIDAQABAoICAC/d7m0IEH7EsfvyUWJA/7R6 +7vRJldZnkWpa8MBFdiHUm4xt0Jdd+0+/D4nDmCmAh0eVoQg5yN+AARInbRCV1sxI +41x+Kn6sy0M0cR/x+qmpEc+Wcr/bpV6PVAaQoLPwXXmnMtqt9RbeX80/4n1dlX7h +7moUWKGGcJHjiGhyhKkGcx7a/W/bhU0WZ7VQqq9teUu6h3HXgs+ljR3OMq70bTau +Ku/DvASu0VWYYJNhlOgmRCRUvPe2FQSvHh7itVIiORvqFTtBoHp/0Z7sjWuMlMxF +J4+8Xau9waDo3J/9kb6Gtq2hP+Iuh+l/W8h6OIiuW1DN0o7H6CDe0idoiofQEm9n +TLgEA1t4JKWNza1+Ifg9cjlPPlBoQViL/iF+lZh8q2FqpX6UZCvr3QJcBLM2A0Um +Tp9F+DvffjWAIhJlj3+mp7KhopIPxBGnHbK9p9uADJXKsxo5lqOlAZxgC4NzyV4/ +WMwJj9H/GeUCO4nnykELqicpZmVaIwIkhbVY5BywvPvR4LaWqew9z9mlUKNYNyLr +gB5uxZntOXUl9RYzTp9Pua83qP+dvRIlY0fZeot5VY7uviSLdq4/vJiQpZwJKHFz +iaHQQs4OqVXVVG/LnDbp2xlOxux06RyT+8ykuraet7z8dfq4RDp6yY18LGPkzV+F +j81+FHFan+AtqJWYXMnBAoIBAQDo5uGfZiZg93iLT2DwHMrOtR2Q/7pYyjtN8ySs +BRPD90uMVILbejrdcUDeV8mCp3qhEwLAbdUBY4BPim/hoYIpc3arfq6WTYbeTis3 +tfMt2UveeiqDnibutR5iTAcLUrTu2ZoaMd80T738/c0Yud+T/vYSeDG4V7LtdVUp +z20FaTKux1YrZpQcNDnqe8V2tRtACj4zQ3m10Opj/0G/dAbqNmPzTrOnSiA4kcjv +ISnPG818D7iZC1QFq2gwzBFNURr2YZw+14GNinVa6fCEgJ7z37YlUMbnDrcnRJ88 +sydipfDXDwQ2pI/9u2Z64kSzHC7NYHtIaEgruF7TNoJnAoqbAoIBAQDBN95wIrOp +5H1/hZUHh0IR+63JL2B89odr6xFEv1Acinp57TXSIKp+nhBVxKkQsHBqovArp7YI +3L4Xx/UBJgrezNTi/o1If1vdSO9PyiIbQADFHQyGX3Ri5GCR8V0KdFmvvyMjvwTq +SuQPAxT/Ijz1nPXJI3pl4t3SDch5XnUppYH0VgjffGqW9nB5lEznQMMBbrRD0Gs9 +d0HkKFayVj3PAWrUPXCC/TK+GZtebK6Ao2cYUYA6W/T4kg0rjZi808dB9Vxtfe31 +Rawb3s1cVG04+SdDRgKqngHc8iPSUKdKc6nSDOSqB0wZu5hjabZXzdDi01Q43U2/ +CHoQviuJCcuRAoIBAErrioTWPV5P/U0DGfHjsTHRfVNZkD5jv7QRlSho8bTGZl0c +CoRDy4/UkMN1hfMroP0TunzgV/b8ZRgxNlBkvhRLek8sj0j2Y347sxdWxoVnM0q8 +DdUNGQUM6ltAjbuMvXtgMHxgsqaHSFyL4GAl2tAm4k2KsKPWQk60wdKTUUS+VHl4 +0jVf6CEyg7b0Xc8T71IoeV3QROTB8cR9Jk9KKbdKC9kG5i/YXokUDIkwJ9zh2rYf +8If65upz+y5HVwGCJ6Q+Ph7RAHHhqmK2gpJ9NaTJwDQ8yd8mErDlGDxUfUT0kIb9 +46MYSOGcWRkKlILxe/TBJqdiNGUsCAT1sfklDiUCggEAWQuhZLZpbGOT/sAWVXjd +VyJRDgXahtyqvm5/79nnVq/vD9/lTOinCmFYD97pN3rI5CwhWU0aVG0+4gDSBex9 +V/64IcDEZePj91BUkcYK/9n4QN9JVWgKYET1yGyev2Gtr5P74s52um83OT/nXklu +JJdoooDKOMhcCCE4Ac8pWb8f6/X2cuCI0vfSEAXrhyvOcwuM4i/cLGCYqkh45Alg +xNTXYebKwmNkDj4I33Rg24Hy0j9FRB/6/s94aFkCSgujqd8k8IT3tHCeh92fcOyr +xXT1xkgulGjrXOLu5U8sOeCiI96zRzTDupw895vRYBfHK7HO/8HlwaNrdenecHJm +MQKCAQEAjFUsJ33nDP724nNBOFe3tv3+XB8btILGpTf1iri8rxybxYs+wGDaj/uC +Y5BWO4jAUlJkyLmAuixDbSLQ1Yd8gfRPlsp+hLJ38IxGaliBfSu24mQPwiLzWDCr +zWbbzZcwvgfixtjK3yn6kIWG9c8b7x1PxPAPCz0lh4+UJ+xTrTxlbWLBqtgU7R5D +Yv8zRRG+dZnYaRZ5a1PQiUTWhyrago4ZcfIf/y7xA+YOTVUii5vd0wwlPIBuoy/c +pQL1UTDbYifCMYVMiTR3u3WEK+RZyFi7h+8poWg5j+AoU4KzhTYcVQubih3PfVZP +yKK0y/oL8+6NAPNNsSb7vph1V0King== +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/theme_with_missing_image.crx b/chrome/test/data/extensions/theme_with_missing_image.crx index 8f9b355..3738d587 100644 --- a/chrome/test/data/extensions/theme_with_missing_image.crx +++ b/chrome/test/data/extensions/theme_with_missing_image.crx Binary files differ
diff --git a/chrome/test/data/extensions/webview_listener.crx b/chrome/test/data/extensions/webview_listener.crx index bcb2e74..b0783455 100644 --- a/chrome/test/data/extensions/webview_listener.crx +++ b/chrome/test/data/extensions/webview_listener.crx Binary files differ
diff --git a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html index e936818..3eb9873b 100644 --- a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html +++ b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html
@@ -23,7 +23,7 @@ } function runGetDisplayMedia(constraints) { - navigator.getDisplayMedia(constraints). + navigator.mediaDevices.getDisplayMedia(constraints). then(handleSuccess).catch(handleError); }
diff --git a/chrome/test/data/xr/e2e_test_files/html/generic_webxr_permission_page.html b/chrome/test/data/xr/e2e_test_files/html/generic_webxr_permission_page.html new file mode 100644 index 0000000..834ff0b --- /dev/null +++ b/chrome/test/data/xr/e2e_test_files/html/generic_webxr_permission_page.html
@@ -0,0 +1,33 @@ +<!doctype html> +<!-- +WebXR page with the ability to request permissions. +--> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css"> + </head> + <body> + <canvas id="webgl-canvas"></canvas> + <script src="../../../../../../third_party/WebKit/LayoutTests/resources/testharness.js"></script> + <script src="../resources/webxr_e2e.js"></script> + <script src="../resources/webxr_boilerplate.js"></script> + <script> + var lastPermissionRequestSucceeded = false; + var storedValue = null; + function requestPermission(permissionObject, storeValue) { + navigator.getUserMedia(permissionObject, + (val) => { + lastPermissionRequestSucceeded = true; + if (storeValue) { + storedValue = val; + } + finishJavaScriptStep(); + }, + () => { + lastPermissionRequestSucceeded = false; + finishJavaScriptStep(); + }); + } + </script> + </body> +</html>
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 45d27991..72ecbb35 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/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("//base/android/jni_generator/jni_exception_list.gni") import("//build/buildflag_header.gni") import("//build/config/features.gni") import("//build/config/sanitizers/sanitizers.gni") @@ -593,12 +592,6 @@ } if (is_android) { - generate_jni_registration("cast_shell_jni_registration") { - target = ":cast_shell_apk" - output = "$root_gen_dir/chromecast/android/${target_name}.h" - exception_files = jni_exception_files - } - android_assets("cast_shell_apk_assets") { assert(v8_use_external_startup_data)
diff --git a/chromecast/android/BUILD.gn b/chromecast/android/BUILD.gn index 6bc8eed..2aebd607 100644 --- a/chromecast/android/BUILD.gn +++ b/chromecast/android/BUILD.gn
@@ -15,7 +15,6 @@ deps = [ "//base", - "//chromecast:cast_shell_jni_registration", "//chromecast:cast_shell_lib", "//chromecast:chromecast_buildflags", "//chromecast/app", @@ -30,19 +29,6 @@ "//skia", ] - # Explicit dependencies required for JNI registration to be able to find the - # native side functions. - if (is_component_build) { - deps += [ - "//device/bluetooth", - "//device/gamepad", - "//media/midi", - "//ui/android", - "//ui/events/devices", - "//ui/shell_dialogs", - ] - } - if (is_cast_using_cma_backend) { deps += [ "//chromecast/media/cma/backend/android:cast_media_android" ] }
diff --git a/chromecast/app/android/cast_jni_loader.cc b/chromecast/app/android/cast_jni_loader.cc index 705d49b..af40022 100644 --- a/chromecast/app/android/cast_jni_loader.cc +++ b/chromecast/app/android/cast_jni_loader.cc
@@ -3,9 +3,6 @@ // found in the LICENSE file. #include "base/android/jni_android.h" -#include "base/android/library_loader/library_loader_hooks.h" -#include "base/bind.h" -#include "chromecast/android/cast_shell_jni_registration.h" #include "chromecast/app/cast_main_delegate.h" #include "content/public/app/content_jni_onload.h" #include "content/public/app/content_main.h" @@ -14,10 +11,6 @@ // This is called by the VM when the shared library is first loaded. JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { base::android::InitVM(vm); - JNIEnv* env = base::android::AttachCurrentThread(); - if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) { - return -1; - } if (!content::android::OnJNIOnLoadInit()) return false;
diff --git a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc index 55b5531..b8a1c44 100644 --- a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc +++ b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -165,7 +165,7 @@ } ui::AXEvent event; - event.id = aura_obj->GetUniqueId().Get(); + event.id = aura_obj->GetUniqueId(); event.event_type = event_type; event_bundle.events.push_back(event);
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index cf40992..cb9bb1e8 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -81,6 +81,7 @@ "//chromeos/resources", "//chromeos/services/assistant/public/proto", "//chromeos/strings", + "//libassistant/shared/internal_api:fuchsia_api_helper", "//libassistant/shared/internal_api/c:api_wrappers_entrypoint", "//libassistant/shared/public", "//libassistant/shared/public:export",
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index f499a7c..969a47c 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -83,6 +83,7 @@ const char kQuicHostWhitelist[] = "host_whitelist"; const char kQuicEnableSocketRecvOptimization[] = "enable_socket_recv_optimization"; +const char kQuicVersion[] = "quic_version"; // AsyncDNS experiment dictionary name. const char kAsyncDnsFieldTrialName[] = "AsyncDNS"; @@ -196,6 +197,29 @@ return result; } +quic::QuicTransportVersionVector ParseQuicVersions( + const std::string& quic_versions) { + quic::QuicTransportVersionVector supported_versions; + quic::QuicTransportVersionVector all_supported_versions = + quic::AllSupportedTransportVersions(); + + for (const base::StringPiece& version : base::SplitStringPiece( + quic_versions, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { + auto it = all_supported_versions.begin(); + while (it != all_supported_versions.end()) { + if (quic::QuicVersionToString(*it) == version) { + supported_versions.push_back(*it); + // Remove the supported version to deduplicate versions extracted from + // |quic_versions|. + all_supported_versions.erase(it); + break; + } + ++it; + } + } + return supported_versions; +} + } // namespace URLRequestContextConfig::QuicHint::QuicHint(const std::string& host, @@ -303,6 +327,15 @@ effective_experimental_options->Remove(it.key(), nullptr); continue; } + + std::string quic_version_string; + if (quic_args->GetString(kQuicVersion, &quic_version_string)) { + quic::QuicTransportVersionVector supported_versions = + ParseQuicVersions(quic_version_string); + if (!supported_versions.empty()) + session_params->quic_supported_versions = supported_versions; + } + std::string quic_connection_options; if (quic_args->GetString(kQuicConnectionOptions, &quic_connection_options)) {
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc index 149b9bb..34448c91 100644 --- a/components/cronet/url_request_context_config_unittest.cc +++ b/components/cronet/url_request_context_config_unittest.cc
@@ -281,6 +281,108 @@ EXPECT_EQ(42.0, config.network_thread_priority.value()); } +TEST(URLRequestContextConfigTest, SetSupportedQuicVersion) { + base::test::ScopedTaskEnvironment scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO); + + URLRequestContextConfig config( + // Enable QUIC. + true, + // QUIC User Agent ID. + "Default QUIC User Agent ID", + // Enable SPDY. + true, + // Enable Brotli. + false, + // Type of http cache. + URLRequestContextConfig::HttpCacheType::DISK, + // Max size of http cache in bytes. + 1024000, + // Disable caching for HTTP responses. Other information may be stored in + // the cache. + false, + // Storage path for http cache and cookie storage. + "/data/data/org.chromium.net/app_cronet_test/test_storage", + // Accept-Language request header field. + "foreign-language", + // User-Agent request header field. + "fake agent", + // JSON encoded experimental options. + "{\"QUIC\":{\"quic_version\":\"QUIC_VERSION_44\"}}", + // MockCertVerifier to use for testing purposes. + std::unique_ptr<net::CertVerifier>(), + // Enable network quality estimator. + false, + // Enable Public Key Pinning bypass for local trust anchors. + true, + // Optional network thread priority. + base::Optional<double>()); + + net::URLRequestContextBuilder builder; + net::NetLog net_log; + config.ConfigureURLRequestContextBuilder(&builder, &net_log); + // Set a ProxyConfigService to avoid DCHECK failure when building. + builder.set_proxy_config_service( + std::make_unique<net::ProxyConfigServiceFixed>( + net::ProxyConfigWithAnnotation::CreateDirect())); + std::unique_ptr<net::URLRequestContext> context(builder.Build()); + const net::HttpNetworkSession::Params* params = + context->GetNetworkSessionParams(); + EXPECT_EQ(params->quic_supported_versions.size(), 1u); + EXPECT_EQ(params->quic_supported_versions[0], quic::QUIC_VERSION_44); +} + +TEST(URLRequestContextConfigTest, SetUnsupportedQuicVersion) { + base::test::ScopedTaskEnvironment scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO); + + URLRequestContextConfig config( + // Enable QUIC. + true, + // QUIC User Agent ID. + "Default QUIC User Agent ID", + // Enable SPDY. + true, + // Enable Brotli. + false, + // Type of http cache. + URLRequestContextConfig::HttpCacheType::DISK, + // Max size of http cache in bytes. + 1024000, + // Disable caching for HTTP responses. Other information may be stored in + // the cache. + false, + // Storage path for http cache and cookie storage. + "/data/data/org.chromium.net/app_cronet_test/test_storage", + // Accept-Language request header field. + "foreign-language", + // User-Agent request header field. + "fake agent", + // JSON encoded experimental options. + "{\"QUIC\":{\"quic_version\":\"QUIC_VERSION_33\"}}", + // MockCertVerifier to use for testing purposes. + std::unique_ptr<net::CertVerifier>(), + // Enable network quality estimator. + false, + // Enable Public Key Pinning bypass for local trust anchors. + true, + // Optional network thread priority. + base::Optional<double>()); + + net::URLRequestContextBuilder builder; + net::NetLog net_log; + config.ConfigureURLRequestContextBuilder(&builder, &net_log); + // Set a ProxyConfigService to avoid DCHECK failure when building. + builder.set_proxy_config_service( + std::make_unique<net::ProxyConfigServiceFixed>( + net::ProxyConfigWithAnnotation::CreateDirect())); + std::unique_ptr<net::URLRequestContext> context(builder.Build()); + const net::HttpNetworkSession::Params* params = + context->GetNetworkSessionParams(); + EXPECT_EQ(params->quic_supported_versions.size(), 1u); + EXPECT_EQ(params->quic_supported_versions[0], quic::QUIC_VERSION_43); +} + TEST(URLRequestContextConfigTest, SetQuicServerMigrationOptions) { base::test::ScopedTaskEnvironment scoped_task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO);
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc index 2d916ed..f14de39 100644 --- a/components/exo/layer_tree_frame_sink_holder.cc +++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -60,7 +60,8 @@ gfx::Rect(holder->last_frame_size_in_pixels_), gfx::Transform()); frame.render_pass_list.push_back(std::move(pass)); holder->last_frame_resources_.clear(); - holder->frame_sink_->SubmitCompositorFrame(std::move(frame)); + holder->frame_sink_->SubmitCompositorFrame(std::move(frame), + /*show_hit_test_borders=*/false); // Delete sink holder immediately if not waiting for resources to be // reclaimed. @@ -84,7 +85,8 @@ last_frame_resources_.clear(); for (auto& resource : frame.resource_list) last_frame_resources_.push_back(resource.id); - frame_sink_->SubmitCompositorFrame(std::move(frame)); + frame_sink_->SubmitCompositorFrame(std::move(frame), + /*show_hit_test_borders=*/false); } void LayerTreeFrameSinkHolder::DidNotProduceFrame(
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc index 37319be..56e1543 100644 --- a/components/guest_view/browser/guest_view_base.cc +++ b/components/guest_view/browser/guest_view_base.cc
@@ -109,13 +109,6 @@ } } - void OnPageScaleFactorChanged(float page_scale_factor) override { - if (destroyed_) - return; - - guest_->web_contents()->SetPageScale(page_scale_factor); - } - void DidUpdateAudioMutingState(bool muted) override { if (destroyed_) return;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index ace4479..75dbd33 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -11783,7 +11783,7 @@ origins named by subdomains; e.g. specifying https://example.com/ will also cause https://foo.example.com/ to be isolated as part of the https://example.com/ site. - If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOrigins and SitePerProcess will be disabled. Users will still be able to enable IsolateOrigins manually. + If the policy is disabled, then both IsolateOrigins and SitePerProcess features will be disabled. Users will still be able to enable IsolateOrigins manually, via command line flags. If the policy is not configured, the user will be able to change this setting. On <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>, it is recommended to also set the <ph name="DEVICE_LOGIN_SCREEN_ISOLATE_ORIGINS_POLICY_NAME">DeviceLoginScreenIsolateOrigins</ph> device policy to the same value. If the values specified by the two policies don't match, a delay may be incurred when entering a user session while the value specified by user policy is being applied. @@ -11807,7 +11807,7 @@ 'desc': ''' You might want to look at the IsolateOrigins policy setting to get the best of both worlds, isolation and limited impact for users, by using IsolateOrigins with a list of the sites you want to isolate. This setting, SitePerProcess, isolates all sites. If the policy is enabled, each site will run in its own process. - If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOrigins and SitePerProcess will be disabled. Users will still be able to enable SitePerProcess manually. + If the policy is disabled, then both IsolateOrigins and SitePerProcess features will be disabled. Users will still be able to enable SitePerProcess manually, via command line flags. If the policy is not configured, the user will be able to change this setting. On <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>, it is recommended to also set the <ph name="DEVICE_LOGIN_SCREEN_SITE_PER_PROCESS_POLICY_NAME">DeviceLoginScreenSitePerProcess</ph> device policy to the same value. If the values specified by the two policies don't match, a delay may be incurred when entering a user session while the value specified by user policy is being applied. @@ -11831,7 +11831,7 @@ 'desc': ''' This policy applies to the sign-in screen. Please see also the <ph name="ISOLATE_ORIGINS_POLICY_NAME">IsolateOrigins</ph> policy which applies to the user session. It is recommended to set both policies to the same value. If the values don't match, a delay may be incurred when entering a user session while the value specified by user policy is being applied. If the policy is enabled, each of the named origins in a comma-separated list will run in its own process. This will also isolate origins named by subdomains; e.g. specifying https://example.com/ will also cause https://foo.example.com/ to be isolated as part of the https://example.com/ site. - If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOrigins and SitePerProcess will be disabled. Users will still be able to enable IsolateOrigins manually. + If the policy is disabled, both IsolateOrigins and SitePerProcess features will be disabled. Users will still be able to enable IsolateOrigins manually, via command line flags. If the policy is not configured, the platform default site isolation settings will be used for the sign-in screen. ''', }, @@ -11853,7 +11853,7 @@ This policy applies to the sign-in screen. Please see also the <ph name="SITE_PER_PROCESS_POLICY_NAME">SitePerProcess</ph> policy which applies to the user session. It is recommended to set both policies to the same value. If the values don't match, a delay may be incurred when entering a user session while the value specified by user policy is being applied. You might want to look at the IsolateOrigins policy setting to get the best of both worlds, isolation and limited impact for users, by using IsolateOrigins with a list of the sites you want to isolate. This setting, SitePerProcess, isolates all sites. If the policy is enabled, each site will run in its own process. - If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOrigins and SitePerProcess will be disabled. Users will still be able to enable SitePerProcess manually. + If the policy is disabled, both IsolateOrigins and SitePerProcess features will be disabled. Users will still be able to enable SitePerProcess manually, via command line flags. If the policy is not configured, the user will be able to change this setting. ''', }, @@ -11877,7 +11877,7 @@ origins named by subdomains; e.g. specifying https://example.com/ will also cause https://foo.example.com/ to be isolated as part of the https://example.com/ site. - If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOriginsAndroid and SitePerProcessAndroid will be disabled. Users will still be able to enable IsolateOrigins manually. + If the policy is disabled, no explicit Site Isolation will happen and field trials of IsolateOriginsAndroid and SitePerProcessAndroid will be disabled. Users will still be able to enable IsolateOrigins manually, via command line flag. If the policy is not configured, the user will be able to change this setting. NOTE: On Android, Site Isolation is experimental. Support will improve over time, but currently it may cause performance problems.
diff --git a/components/ukm/BUILD.gn b/components/ukm/BUILD.gn index 44d801a0..3e66c69 100644 --- a/components/ukm/BUILD.gn +++ b/components/ukm/BUILD.gn
@@ -9,6 +9,8 @@ # URLs for top-level navigations. static_library("ukm") { sources = [ + "app_source_url_recorder.cc", + "app_source_url_recorder.h", "persisted_logs_metrics_impl.cc", "persisted_logs_metrics_impl.h", "ukm_pref_names.cc", @@ -32,6 +34,7 @@ deps = [ "//base", + "//components/crx_file", "//components/data_use_measurement/core", "//components/metrics", "//components/prefs", @@ -82,6 +85,7 @@ source_set("unit_tests") { testonly = true sources = [ + "app_source_url_recorder_test.cc", "observers/sync_disable_observer_unittest.cc", "ukm_service_unittest.cc", ]
diff --git a/components/ukm/DEPS b/components/ukm/DEPS index 053cb841a..3b07d2c 100644 --- a/components/ukm/DEPS +++ b/components/ukm/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+components/crx_file", "+components/metrics", "+components/prefs", "+components/unified_consent", @@ -13,4 +14,4 @@ ".*unittest\.cc": [ "+components/sync_preferences/testing_pref_service_syncable.h", ] -} \ No newline at end of file +}
diff --git a/components/ukm/content/app_source_url_recorder.cc b/components/ukm/app_source_url_recorder.cc similarity index 95% rename from components/ukm/content/app_source_url_recorder.cc rename to components/ukm/app_source_url_recorder.cc index 93f16c5..7bd80a7 100644 --- a/components/ukm/content/app_source_url_recorder.cc +++ b/components/ukm/app_source_url_recorder.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/ukm/content/app_source_url_recorder.h" +#include "components/ukm/app_source_url_recorder.h" #include "base/atomic_sequence_num.h" #include "components/crx_file/id_util.h"
diff --git a/components/ukm/content/app_source_url_recorder.h b/components/ukm/app_source_url_recorder.h similarity index 83% rename from components/ukm/content/app_source_url_recorder.h rename to components/ukm/app_source_url_recorder.h index 4b98434c..ca1bc68 100644 --- a/components/ukm/content/app_source_url_recorder.h +++ b/components/ukm/app_source_url_recorder.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_UKM_CONTENT_APP_SOURCE_URL_RECORDER_H_ -#define COMPONENTS_UKM_CONTENT_APP_SOURCE_URL_RECORDER_H_ +#ifndef COMPONENTS_UKM_APP_SOURCE_URL_RECORDER_H_ +#define COMPONENTS_UKM_APP_SOURCE_URL_RECORDER_H_ #include "services/metrics/public/cpp/ukm_source_id.h" @@ -37,4 +37,4 @@ } // namespace ukm -#endif // COMPONENTS_UKM_CONTENT_APP_SOURCE_URL_RECORDER_H_ +#endif // COMPONENTS_UKM_APP_SOURCE_URL_RECORDER_H_
diff --git a/components/ukm/content/app_source_url_recorder_test.cc b/components/ukm/app_source_url_recorder_test.cc similarity index 88% rename from components/ukm/content/app_source_url_recorder_test.cc rename to components/ukm/app_source_url_recorder_test.cc index ae4807b..444dedd4 100644 --- a/components/ukm/content/app_source_url_recorder_test.cc +++ b/components/ukm/app_source_url_recorder_test.cc
@@ -2,22 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/ukm/content/app_source_url_recorder.h" +#include "components/ukm/app_source_url_recorder.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" #include "components/ukm/test_ukm_recorder.h" -#include "content/public/test/test_renderer_host.h" #include "services/metrics/public/cpp/ukm_source.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace ukm { -class AppSourceUrlRecorderTest : public content::RenderViewHostTestHarness { +class AppSourceUrlRecorderTest : public testing::Test { public: void SetUp() override { scoped_feature_list_.InitAndEnableFeature(kUkmAppLogging); - content::RenderViewHostTestHarness::SetUp(); } protected: @@ -30,6 +29,7 @@ } base::test::ScopedFeatureList scoped_feature_list_; + base::test::ScopedTaskEnvironment scoped_task_environment_; TestAutoSetUkmRecorder test_ukm_recorder_; };
diff --git a/components/ukm/content/BUILD.gn b/components/ukm/content/BUILD.gn index 42ee889..203c75c 100644 --- a/components/ukm/content/BUILD.gn +++ b/components/ukm/content/BUILD.gn
@@ -4,14 +4,11 @@ static_library("content") { sources = [ - "app_source_url_recorder.cc", - "app_source_url_recorder.h", "source_url_recorder.cc", "source_url_recorder.h", ] deps = [ "//base", - "//components/crx_file", "//content/public/browser", "//services/metrics/public/cpp:metrics_cpp", "//services/metrics/public/cpp:ukm_builders", @@ -23,7 +20,6 @@ source_set("unit_tests") { testonly = true sources = [ - "app_source_url_recorder_test.cc", "source_url_recorder_test.cc", ] deps = [
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index b4e7cdf..e1fb185 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -451,15 +451,16 @@ child_initiated_synchronization_event && !last_surface_has_dependent_frame; - current_surface = CreateSurface(surface_info, block_activation_on_parent); - last_created_surface_id_ = SurfaceId(frame_sink_id_, local_surface_id); - MaybeEvictSurfaces(); - // If the surface was immediately evicted, don't accept the CompositorFrame. - if (!last_created_surface_id_.is_valid()) { + // Don't recreate a surface that was previously evicted. Drop the + // CompositorFrame and return all its resources. + if (local_surface_id.parent_sequence_number() <= + last_evicted_parent_sequence_number_) { TRACE_EVENT_INSTANT0("viz", "Submit rejected to evicted surface", TRACE_EVENT_SCOPE_THREAD); return SubmitResult::ACCEPTED; } + current_surface = CreateSurface(surface_info, block_activation_on_parent); + last_created_surface_id_ = SurfaceId(frame_sink_id_, local_surface_id); if (!current_surface) { TRACE_EVENT_INSTANT0("viz", "Surface Invariants Violation",
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc index 4d5f2e2..2b9ebe5 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -157,7 +157,9 @@ return hit_test_region_list; } -void DirectLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) { +void DirectLayerTreeFrameSink::SubmitCompositorFrame( + CompositorFrame frame, + bool show_hit_test_borders) { DCHECK(frame.metadata.begin_frame_ack.has_damage); DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, frame.metadata.begin_frame_ack.sequence_number);
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h index e76bb6c4..24d6f45 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -68,7 +68,8 @@ // LayerTreeFrameSink implementation. bool BindToClient(cc::LayerTreeFrameSinkClient* client) override; void DetachFromClient() override; - void SubmitCompositorFrame(CompositorFrame frame) override; + void SubmitCompositorFrame(CompositorFrame frame, + bool show_hit_test_borders) override; void DidNotProduceFrame(const BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const SharedBitmapId& id) override;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc index c4c52773..a4546078 100644 --- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc +++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -104,7 +104,8 @@ auto frame = CompositorFrameBuilder() .AddRenderPass(display_rect_, damage_rect) .Build(); - layer_tree_frame_sink_->SubmitCompositorFrame(std::move(frame)); + layer_tree_frame_sink_->SubmitCompositorFrame( + std::move(frame), /*show_hit_test_borders=*/false); } void SendRenderPassList(RenderPassList* pass_list) { @@ -112,7 +113,8 @@ .SetRenderPassList(std::move(*pass_list)) .Build(); pass_list->clear(); - layer_tree_frame_sink_->SubmitCompositorFrame(std::move(frame)); + layer_tree_frame_sink_->SubmitCompositorFrame( + std::move(frame), /*show_hit_test_borders=*/false); } void SetUp() override {
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index 759dd34..0c7902d 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -1194,8 +1194,8 @@ } // Verifies that if a LocalSurfaceId belonged to a surface that doesn't -// exist anymore, it can still be reused for new surfaces. -TEST_F(SurfaceSynchronizationTest, LocalSurfaceIdIsReusable) { +// exist anymore, it can not be recreated. +TEST_F(SurfaceSynchronizationTest, LocalSurfaceIdIsNotReusable) { const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3); @@ -1220,11 +1220,11 @@ EXPECT_EQ(nullptr, GetSurfaceForId(child_id)); - // Submit another frame with the same local surface id. This should work fine - // and a new surface must be created. + // Submit another frame with the same local surface id. The surface should not + // be recreated. child_support1().SubmitCompositorFrame(child_id.local_surface_id(), MakeDefaultCompositorFrame()); - EXPECT_NE(nullptr, GetSurfaceForId(child_id)); + EXPECT_EQ(nullptr, GetSurfaceForId(child_id)); } // This test verifies that a crash does not occur if garbage collection is @@ -2951,25 +2951,26 @@ // Parent-initiated synchronizaton event: const SurfaceId child_id3 = MakeSurfaceId(kChildFrameSink1, 2, 2); - // Evict |child_id1|. - child_support1().EvictSurface(child_id1.local_surface_id()); - - // Submit a CompositorFrame to |child_id1|. It should get marked for - // destruction immediately. + // Submit a CompositorFrame to |child_id1|. child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), MakeDefaultCompositorFrame()); + + // Evict |child_id1|. It should get marked for destruction immediately. + child_support1().EvictSurface(child_id1.local_surface_id()); EXPECT_TRUE(IsMarkedForDestruction(child_id1)); - // Submit a CompositorFrame to |child_id2|. It should also get marked for - // destruction because it has the same parent sequence number as |child_id1|. + // Submit a CompositorFrame to |child_id2|. This CompositorFrame should be + // immediately rejected because |child_id2| has the same parent sequence + // number as |child_id1|. child_support1().SubmitCompositorFrame(child_id2.local_surface_id(), MakeDefaultCompositorFrame()); - EXPECT_TRUE(IsMarkedForDestruction(child_id2)); + EXPECT_EQ(nullptr, GetSurfaceForId(child_id2)); - // Submit a CompositorFrame to |child_id3|. It should not be marked for - // destruction. + // Submit a CompositorFrame to |child_id3|. It should not be accepted and not + // marked for destruction. child_support1().SubmitCompositorFrame(child_id3.local_surface_id(), MakeDefaultCompositorFrame()); + ASSERT_NE(nullptr, GetSurfaceForId(child_id3)); EXPECT_FALSE(IsMarkedForDestruction(child_id3)); }
diff --git a/components/viz/test/test_layer_tree_frame_sink.cc b/components/viz/test/test_layer_tree_frame_sink.cc index 8ccc2c8..6c6c8e0 100644 --- a/components/viz/test/test_layer_tree_frame_sink.cc +++ b/components/viz/test/test_layer_tree_frame_sink.cc
@@ -155,7 +155,8 @@ test_client_->DisplayReceivedLocalSurfaceId(local_surface_id); } -void TestLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) { +void TestLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame, + bool show_hit_test_borders) { DCHECK(frame.metadata.begin_frame_ack.has_damage); DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, frame.metadata.begin_frame_ack.sequence_number);
diff --git a/components/viz/test/test_layer_tree_frame_sink.h b/components/viz/test/test_layer_tree_frame_sink.h index 68000733..82e93e7 100644 --- a/components/viz/test/test_layer_tree_frame_sink.h +++ b/components/viz/test/test_layer_tree_frame_sink.h
@@ -90,7 +90,8 @@ bool BindToClient(cc::LayerTreeFrameSinkClient* client) override; void DetachFromClient() override; void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) override; - void SubmitCompositorFrame(CompositorFrame frame) override; + void SubmitCompositorFrame(CompositorFrame frame, + bool show_hit_test_borders) override; void DidNotProduceFrame(const BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const SharedBitmapId& id) override;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7a179dc..26b1e7b 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -465,8 +465,6 @@ "background_fetch/storage/match_requests_task.h", "background_fetch/storage/start_next_pending_request_task.cc", "background_fetch/storage/start_next_pending_request_task.h", - "background_fetch/storage/update_registration_ui_task.cc", - "background_fetch/storage/update_registration_ui_task.h", "background_sync/background_sync_context.cc", "background_sync/background_sync_context.h", "background_sync/background_sync_manager.cc",
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc index 392aa22..0cf248fa 100644 --- a/content/browser/background_fetch/background_fetch_context.cc +++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -37,7 +37,6 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) : browser_context_(browser_context), service_worker_context_(service_worker_context), - event_dispatcher_(service_worker_context), registration_notifier_( std::make_unique<BackgroundFetchRegistrationNotifier>()), delegate_proxy_(browser_context_->GetBackgroundFetchDelegate()), @@ -49,23 +48,23 @@ data_manager_ = std::make_unique<BackgroundFetchDataManager>( browser_context_, service_worker_context, cache_storage_context, std::move(quota_manager_proxy)); - scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get()); - delegate_proxy_.SetClickEventDispatcher(base::BindRepeating( - &BackgroundFetchContext::DispatchClickEvent, weak_factory_.GetWeakPtr())); + scheduler_ = std::make_unique<BackgroundFetchScheduler>( + data_manager_.get(), registration_notifier_.get(), &delegate_proxy_, + service_worker_context_); } BackgroundFetchContext::~BackgroundFetchContext() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - service_worker_context_->RemoveObserver(this); - data_manager_->RemoveObserver(this); + service_worker_context_->RemoveObserver(scheduler_.get()); + data_manager_->RemoveObserver(scheduler_.get()); } void BackgroundFetchContext::InitializeOnIOThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - service_worker_context_->AddObserver(this); + service_worker_context_->AddObserver(scheduler_.get()); - data_manager_->AddObserver(this); + data_manager_->AddObserver(scheduler_.get()); data_manager_->InitializeOnIOThread(); data_manager_->GetInitializationData( base::BindOnce(&BackgroundFetchContext::DidGetInitializationData, @@ -82,10 +81,12 @@ background_fetch::RecordRegistrationsOnStartup(initialization_data.size()); for (auto& data : initialization_data) { - CreateController(data.registration_id, data.registration, data.options, - data.icon, data.ui_title, data.num_completed_requests, - data.num_requests, std::move(data.active_fetch_requests), - /* start_paused = */ false); + for (auto& observer : data_manager_->observers()) { + observer.OnRegistrationLoadedAtStartup( + data.registration_id, data.registration, data.options, data.icon, + data.num_completed_requests, data.num_requests, + data.active_fetch_requests); + } } } @@ -123,12 +124,8 @@ } BackgroundFetchRegistration updated_registration(registration); - - // The data manager only has the number of bytes from completed downloads, so - // augment this with the number of downloaded bytes from in-progress jobs. - DCHECK(job_controllers_.count(registration.unique_id)); - updated_registration.downloaded += - job_controllers_[registration.unique_id]->GetInProgressDownloadedBytes(); + for (auto& observer : data_manager_->observers()) + observer.OnRegistrationQueried(&updated_registration); std::move(callback).Run(error, updated_registration); } @@ -194,8 +191,7 @@ std::move(ukm_data), frame_tree_node_id, permission)); if (permission != BackgroundFetchPermission::BLOCKED) { - // TODO(crbug.com/886896): Passed paused flag to CreateRegistration. - data_manager_->BackgroundFetchDataManager::CreateRegistration( + data_manager_->CreateRegistration( registration_id, requests, options, icon, permission == BackgroundFetchPermission::ASK /* start_paused */, base::BindOnce(&BackgroundFetchContext::DidCreateRegistration, @@ -204,8 +200,6 @@ } // No permission, the fetch should be rejected. - background_fetch::RecordRegistrationCreatedError( - blink::mojom::BackgroundFetchError::PERMISSION_DENIED); std::move(fetch_callbacks_[registration_id]) .Run(blink::mojom::BackgroundFetchError::PERMISSION_DENIED, base::nullopt); @@ -223,8 +217,6 @@ const BackgroundFetchRegistration& registration) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - background_fetch::RecordRegistrationCreatedError(error); - auto iter = fetch_callbacks_.find(registration_id); // The fetch might have been abandoned already if the Service Worker was @@ -253,312 +245,18 @@ blink::mojom::BackgroundFetchService::UpdateUICallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // The registration must a) still be active, or b) have completed/failed (not - // aborted) with the waitUntil promise from that event not yet resolved. - if (!job_controllers_.count(registration_id.unique_id())) { - std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID); - return; - } - - data_manager_->UpdateRegistrationUI(registration_id, title, icon, - std::move(callback)); -} - -void BackgroundFetchContext::OnServiceWorkerDatabaseCorrupted( - int64_t service_worker_registration_id) { - AbandonFetches(service_worker_registration_id); -} - -void BackgroundFetchContext::OnQuotaExceeded( - const BackgroundFetchRegistrationId& registration_id) { - auto job_it = job_controllers_.find(registration_id.unique_id()); - if (job_it != job_controllers_.end() && job_it->second) - job_it->second->Abort(FailureReason::QUOTA_EXCEEDED); -} - -void BackgroundFetchContext::AbandonFetches( - int64_t service_worker_registration_id) { - // Abandon all active fetches associated with this service worker. - // BackgroundFetchJobController::Abort() will eventually lead to deletion of - // the controller from job_controllers, hence we can't use a range based - // for-loop here. - for (auto iter = job_controllers_.begin(); iter != job_controllers_.end(); - /* no_increment */) { - auto saved_iter = iter; - iter++; - if (service_worker_registration_id == - blink::mojom::kInvalidServiceWorkerRegistrationId || - saved_iter->second->registration_id() - .service_worker_registration_id() == - service_worker_registration_id) { - DCHECK(saved_iter->second); - - saved_iter->second->Abort(FailureReason::SERVICE_WORKER_UNAVAILABLE); - } - } - - for (auto iter = fetch_callbacks_.begin(); iter != fetch_callbacks_.end(); - /* no increment */) { - if (service_worker_registration_id == - blink::mojom::kInvalidServiceWorkerRegistrationId || - iter->first.service_worker_registration_id() == - service_worker_registration_id) { - DCHECK(iter->second); - std::move(iter->second) - .Run(blink::mojom::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE, - base::nullopt /* BackgroundFetchRegistration */); - iter = fetch_callbacks_.erase(iter); - } else - iter++; - } -} - -void BackgroundFetchContext::OnRegistrationCreated( - const BackgroundFetchRegistrationId& registration_id, - const BackgroundFetchRegistration& registration, - const BackgroundFetchOptions& options, - const SkBitmap& icon, - int num_requests, - bool start_paused) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (hang_registration_creation_for_testing_) { - // Hang here, to allow time for testing races. For instance, this helps us - // test the behavior when a service worker gets unregistered before the - // controller can be created. - return; - } - - // TODO(peter): When this moves to the BackgroundFetchScheduler, only create - // a controller when the background fetch can actually be started. - - CreateController(registration_id, registration, options, icon, options.title, - 0u /* num_completed_requests */, num_requests, - {} /* active_fetch_requests */, start_paused); -} - -void BackgroundFetchContext::OnUpdatedUI( - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - auto iter = job_controllers_.find(registration_id.unique_id()); - if (iter != job_controllers_.end()) - iter->second->UpdateUI(title, icon); -} - -void BackgroundFetchContext::OnRegistrationDeleted( - int64_t service_worker_registration_id, - const GURL& pattern) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - AbandonFetches(service_worker_registration_id); -} - -void BackgroundFetchContext::OnStorageWiped() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - AbandonFetches(blink::mojom::kInvalidServiceWorkerRegistrationId); -} - -void BackgroundFetchContext::OnFetchStorageError( - const BackgroundFetchRegistrationId& registration_id) { - auto controllers_iter = job_controllers_.find(registration_id.unique_id()); - if (controllers_iter == job_controllers_.end()) - return; - - controllers_iter->second->Abort(FailureReason::SERVICE_WORKER_UNAVAILABLE); -} - -void BackgroundFetchContext::CreateController( - const BackgroundFetchRegistrationId& registration_id, - const BackgroundFetchRegistration& registration, - const BackgroundFetchOptions& options, - const SkBitmap& icon, - const std::string& ui_title, - size_t num_completed_requests, - size_t num_requests, - std::vector<scoped_refptr<BackgroundFetchRequestInfo>> - active_fetch_requests, - bool start_paused) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - auto controller = std::make_unique<BackgroundFetchJobController>( - &delegate_proxy_, scheduler_.get(), registration_id, options, icon, - registration.downloaded, - // Safe because JobControllers are destroyed before RegistrationNotifier. - base::BindRepeating(&BackgroundFetchRegistrationNotifier::Notify, - base::Unretained(registration_notifier_.get())), - base::BindOnce( - &BackgroundFetchContext::DidFinishJob, weak_factory_.GetWeakPtr(), - base::Bind(&background_fetch::RecordSchedulerFinishedError))); - - controller->InitializeRequestStatus(num_completed_requests, num_requests, - std::move(active_fetch_requests), - ui_title, start_paused); - scheduler_->AddJobController(controller.get()); - job_controllers_.emplace(registration_id.unique_id(), std::move(controller)); + // TODO(crbug.com/901909): This call should reject if the event + // is out of scope. + delegate_proxy_.UpdateUI(registration_id.unique_id(), title, icon); + std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE); } void BackgroundFetchContext::Abort( const BackgroundFetchRegistrationId& registration_id, blink::mojom::BackgroundFetchService::AbortCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - - auto controllers_iter = job_controllers_.find(registration_id.unique_id()); - if (controllers_iter == job_controllers_.end()) { - std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID); - return; - } - - controllers_iter->second->Abort(FailureReason::CANCELLED_BY_DEVELOPER); - - DidFinishJob(std::move(callback), registration_id, - FailureReason::CANCELLED_BY_DEVELOPER); -} - -void BackgroundFetchContext::DidFinishJob( - base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback, - const BackgroundFetchRegistrationId& registration_id, - FailureReason failure_reason) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // If the registration was aborted, this will also propagate the event to any - // active JobController, to terminate in-progress requests. - data_manager_->MarkRegistrationForDeletion( - registration_id, - /* check_for_failure= */ failure_reason == FailureReason::NONE, - base::BindOnce(&BackgroundFetchContext::DidMarkForDeletion, - weak_factory_.GetWeakPtr(), registration_id, - std::move(callback))); -} - -void BackgroundFetchContext::DidMarkForDeletion( - const BackgroundFetchRegistrationId& registration_id, - base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback, - blink::mojom::BackgroundFetchError error, - FailureReason failure_reason) { - DCHECK(callback); - std::move(callback).Run(error); - - // It's normal to get INVALID_ID errors here - it means the registration was - // already inactive (marked for deletion). This happens when an abort (from - // developer or from user) races with the download completing/failing, or even - // when two aborts race. - if (error != blink::mojom::BackgroundFetchError::NONE) - return; - - auto controllers_iter = job_controllers_.find(registration_id.unique_id()); - DCHECK(controllers_iter != job_controllers_.end()); - - failure_reason = controllers_iter->second->MergeFailureReason(failure_reason); - blink::mojom::BackgroundFetchResult result = - failure_reason == FailureReason::NONE - ? blink::mojom::BackgroundFetchResult::SUCCESS - : blink::mojom::BackgroundFetchResult::FAILURE; - - auto registration = controllers_iter->second->NewRegistration(result); - DispatchCompletionEvent(registration_id, std::move(registration)); -} - -void BackgroundFetchContext::DispatchCompletionEvent( - const BackgroundFetchRegistrationId& registration_id, - std::unique_ptr<BackgroundFetchRegistration> registration) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - registration_notifier_->Notify(*registration); - - switch (registration->failure_reason) { - case FailureReason::NONE: - DCHECK_EQ(registration->result, - blink::mojom::BackgroundFetchResult::SUCCESS); - event_dispatcher_.DispatchBackgroundFetchSuccessEvent( - registration_id, std::move(registration), - base::BindOnce(&BackgroundFetchContext::CleanupRegistration, - weak_factory_.GetWeakPtr(), registration_id, - blink::mojom::BackgroundFetchResult::SUCCESS, - /* preserve_info_to_dispatch_click_event= */ true)); - return; - case FailureReason::CANCELLED_FROM_UI: - case FailureReason::CANCELLED_BY_DEVELOPER: - DCHECK_EQ(registration->result, - blink::mojom::BackgroundFetchResult::FAILURE); - event_dispatcher_.DispatchBackgroundFetchAbortEvent( - registration_id, std::move(registration), - base::BindOnce(&BackgroundFetchContext::CleanupRegistration, - weak_factory_.GetWeakPtr(), registration_id, - blink::mojom::BackgroundFetchResult::FAILURE, - /* preserve_info_to_dispatch_click_event= */ false)); - return; - case FailureReason::BAD_STATUS: - case FailureReason::FETCH_ERROR: - case FailureReason::SERVICE_WORKER_UNAVAILABLE: - case FailureReason::QUOTA_EXCEEDED: - case FailureReason::TOTAL_DOWNLOAD_SIZE_EXCEEDED: - DCHECK_EQ(registration->result, - blink::mojom::BackgroundFetchResult::FAILURE); - event_dispatcher_.DispatchBackgroundFetchFailEvent( - registration_id, std::move(registration), - base::BindOnce(&BackgroundFetchContext::CleanupRegistration, - weak_factory_.GetWeakPtr(), registration_id, - blink::mojom::BackgroundFetchResult::FAILURE, - /* preserve_info_to_dispatch_click_event= */ true)); - return; - } -} - -void BackgroundFetchContext::CleanupRegistration( - const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchResult background_fetch_result, - bool preserve_info_to_dispatch_click_event) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // Indicate to the renderer that the records for this fetch are no longer - // available. - registration_notifier_->NotifyRecordsUnavailable(registration_id.unique_id()); - - // If we had an active JobController, it is no longer necessary, as the - // notification's UI can no longer be updated after the fetch is aborted, or - // after the waitUntil promise of the - // backgroundfetchsuccess/backgroundfetchfail event has been resolved. Store - // the information we want to persist after the controller is gone, in - // completed_fetches_. - auto controllers_iter = job_controllers_.find(registration_id.unique_id()); - DCHECK(controllers_iter != job_controllers_.end()); - if (preserve_info_to_dispatch_click_event) { - completed_fetches_[registration_id.unique_id()] = std::make_pair( - registration_id, - controllers_iter->second->NewRegistration(background_fetch_result)); - } - job_controllers_.erase(registration_id.unique_id()); - - // Delete the data associated with this fetch. Cache storage will keep the - // downloaded data around so long as there are references to it, and delete - // it once there is none. We don't need to do that accounting. - data_manager_->DeleteRegistration( - registration_id, - base::BindOnce(&background_fetch::RecordRegistrationDeletedError)); -} - -void BackgroundFetchContext::DispatchClickEvent(const std::string& unique_id) { - auto iter = completed_fetches_.find(unique_id); - if (iter != completed_fetches_.end()) { - // The fetch has succeeded or failed. (not aborted/cancelled). - event_dispatcher_.DispatchBackgroundFetchClickEvent( - iter->second.first /* registration_id */, - std::move(iter->second.second) /* registration */, base::DoNothing()); - completed_fetches_.erase(iter); - return; - } - - // The fetch is active. - auto controllers_iter = job_controllers_.find(unique_id); - if (controllers_iter == job_controllers_.end()) - return; - auto registration = controllers_iter->second->NewRegistration( - blink::mojom::BackgroundFetchResult::UNSET); - event_dispatcher_.DispatchBackgroundFetchClickEvent( - controllers_iter->second->registration_id(), std::move(registration), - base::DoNothing()); + scheduler_->Abort(registration_id, FailureReason::CANCELLED_BY_DEVELOPER, + std::move(callback)); } void BackgroundFetchContext::MatchRequests( @@ -605,7 +303,9 @@ std::unique_ptr<BackgroundFetchDataManager> data_manager) { DCHECK(data_manager); data_manager_ = std::move(data_manager); - scheduler_ = std::make_unique<BackgroundFetchScheduler>(data_manager_.get()); + scheduler_ = std::make_unique<BackgroundFetchScheduler>( + data_manager_.get(), registration_notifier_.get(), &delegate_proxy_, + service_worker_context_); } } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_context.h b/content/browser/background_fetch/background_fetch_context.h index c39bf76..c66e1b3 100644 --- a/content/browser/background_fetch/background_fetch_context.h +++ b/content/browser/background_fetch/background_fetch_context.h
@@ -14,29 +14,24 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" -#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/background_fetch_delegate_proxy.h" #include "content/browser/background_fetch/background_fetch_event_dispatcher.h" #include "content/browser/background_fetch/storage/get_initialization_data_task.h" -#include "content/browser/service_worker/service_worker_context_core_observer.h" #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h" namespace storage { -class BlobDataHandle; class QuotaManagerProxy; } namespace content { -class BackgroundFetchJobController; class BackgroundFetchDataManager; struct BackgroundFetchOptions; class BackgroundFetchRegistrationId; class BackgroundFetchRegistrationNotifier; class BackgroundFetchRequestMatchParams; -class BackgroundFetchRequestInfo; class BackgroundFetchScheduler; class BrowserContext; class CacheStorageContextImpl; @@ -49,9 +44,7 @@ // Background Fetch requests function similarly to normal fetches except that // they are persistent across Chromium or service worker shutdown. class CONTENT_EXPORT BackgroundFetchContext - : public BackgroundFetchDataManagerObserver, - public ServiceWorkerContextCoreObserver, - public base::RefCountedThreadSafe<BackgroundFetchContext, + : public base::RefCountedThreadSafe<BackgroundFetchContext, BrowserThread::DeleteOnIOThread> { public: // The BackgroundFetchContext will watch the ServiceWorkerContextWrapper so @@ -130,29 +123,6 @@ const base::Optional<SkBitmap>& icon, blink::mojom::BackgroundFetchService::UpdateUICallback callback); - // BackgroundFetchDataManagerObserver implementation. - void OnRegistrationCreated( - const BackgroundFetchRegistrationId& registration_id, - const BackgroundFetchRegistration& registration, - const BackgroundFetchOptions& options, - const SkBitmap& icon, - int num_requests, - bool start_paused) override; - void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon) override; - void OnServiceWorkerDatabaseCorrupted( - int64_t service_worker_registration_id) override; - void OnQuotaExceeded( - const BackgroundFetchRegistrationId& registration_id) override; - void OnFetchStorageError( - const BackgroundFetchRegistrationId& registration_id) override; - - // ServiceWorkerContextCoreObserver implementation. - void OnRegistrationDeleted(int64_t registration_id, - const GURL& pattern) override; - void OnStorageWiped() override; - private: using GetPermissionCallback = base::OnceCallback<void(BackgroundFetchPermission)>; @@ -166,23 +136,10 @@ BrowserThread::DeleteOnIOThread>; friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; - ~BackgroundFetchContext() override; + ~BackgroundFetchContext(); void ShutdownOnIO(); - // Creates a new Job Controller for the given |registration_id| and |options|, - // which will start fetching the files that are part of the registration. - void CreateController(const BackgroundFetchRegistrationId& registration_id, - const BackgroundFetchRegistration& registration, - const BackgroundFetchOptions& options, - const SkBitmap& icon, - const std::string& ui_title, - size_t num_completed_requests, - size_t num_requests, - std::vector<scoped_refptr<BackgroundFetchRequestInfo>> - active_fetch_requests, - bool start_paused); - // Called when an existing registration has been retrieved from the data // manager. If the registration does not exist then |registration| is nullptr. void DidGetRegistration( @@ -196,29 +153,6 @@ blink::mojom::BackgroundFetchError error, const BackgroundFetchRegistration& registration); - // Called by a JobController when it finishes processing. Also used to - // implement |Abort|. - void DidFinishJob( - base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback, - const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchFailureReason failure_reason); - - // Called when the data manager finishes marking a registration as deleted. - void DidMarkForDeletion( - const BackgroundFetchRegistrationId& registration_id, - base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback, - blink::mojom::BackgroundFetchError error, - blink::mojom::BackgroundFetchFailureReason failure_reason); - - // Called when the sequence of settled fetches for |registration_id| have been - // retrieved from storage, and the Service Worker event can be invoked. - void DidGetSettledFetches( - const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchError error, - blink::mojom::BackgroundFetchFailureReason failure_reason, - std::vector<BackgroundFetchSettledFetch> settled_fetches, - std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles); - // Called when the sequence of matching settled fetches have been received // from storage, and |callback| can be invoked to pass these on to the // renderer. @@ -227,43 +161,17 @@ blink::mojom::BackgroundFetchError error, std::vector<BackgroundFetchSettledFetch> settled_fetches); - // Dispatches an appropriate event (success, fail, abort). - void DispatchCompletionEvent( - const BackgroundFetchRegistrationId& registration_id, - std::unique_ptr<BackgroundFetchRegistration> registration); - - // Called when the notification UI for the background fetch job associated - // with |unique_id| is activated. - void DispatchClickEvent(const std::string& unique_id); - // Called when the data manager finishes getting the initialization data. void DidGetInitializationData( blink::mojom::BackgroundFetchError error, std::vector<background_fetch::BackgroundFetchInitializationData> initialization_data); - // Called when all processing for the |registration_id| has been finished and - // the job is ready to be deleted. - // |preserve_info_to_dispatch_click_event|, when set, preserves the - // registration ID, and the result of the Fetch when it completed, in - // |completed_fetches_|. This is not done when fetch is aborted or cancelled. - // We use this information to propagate BackgroundFetchClicked event to the - // developer, when the user taps the UI. - void CleanupRegistration( - const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchResult background_fetch_result, - bool preserve_info_to_dispatch_click_event = false); - // Switches out |data_manager_| with a DataManager configured for testing // environments. Must be called directly after the constructor. void SetDataManagerForTesting( std::unique_ptr<BackgroundFetchDataManager> data_manager); - // Helper method to abandon ongoing fetches for a given service worker. - // Abandons all of them if |service_worker_registration_id| is set to - // blink::mojom::kInvalidServiceWorkerRegistrationId. - void AbandonFetches(int64_t service_worker_registration_id); - // Check if |origin| has permission to start a fetch. // virtual for testing. void GetPermissionForOrigin(const url::Origin& origin, @@ -284,25 +192,10 @@ std::unique_ptr<BackgroundFetchDataManager> data_manager_; scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; - BackgroundFetchEventDispatcher event_dispatcher_; std::unique_ptr<BackgroundFetchRegistrationNotifier> registration_notifier_; BackgroundFetchDelegateProxy delegate_proxy_; std::unique_ptr<BackgroundFetchScheduler> scheduler_; - // Map from background fetch registration |unique_id|s to active job - // controllers. Must be destroyed before |data_manager_|, |scheduler_| and - // |registration_notifier_|. - std::map<std::string, std::unique_ptr<BackgroundFetchJobController>> - job_controllers_; - - // Map from |unique_id|s to {|registration_id|, |registration|}. - // An entry in here means the fetch has completed. This information is needed - // after the fetch has completed to dispatch the backgroundfetchclick event. - // TODO(crbug.com/857122): Clean this up when the UI is no longer showing. - std::map<std::string, - std::pair<BackgroundFetchRegistrationId, - std::unique_ptr<BackgroundFetchRegistration>>> - completed_fetches_; // Map from BackgroundFetchRegistrationIds to FetchCallbacks for active // fetches. Must be destroyed before |data_manager_| and // |registration_notifier_|. Since FetchCallback is a OnceCallback, please @@ -311,11 +204,6 @@ blink::mojom::BackgroundFetchService::FetchCallback> fetch_callbacks_; - // This is used to hang the fetch logic for testing. For instance, this helps - // us test the behavior when a service worker gets unregistered before the - // controller has been created. - bool hang_registration_creation_for_testing_ = false; - base::WeakPtrFactory<BackgroundFetchContext> weak_factory_; // Must be last. DISALLOW_COPY_AND_ASSIGN(BackgroundFetchContext);
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc index 5fe6581..5367ce5 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.cc +++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -23,7 +23,6 @@ #include "content/browser/background_fetch/storage/mark_request_complete_task.h" #include "content/browser/background_fetch/storage/match_requests_task.h" #include "content/browser/background_fetch/storage/start_next_pending_request_task.h" -#include "content/browser/background_fetch/storage/update_registration_ui_task.h" #include "content/browser/cache_storage/cache_storage_manager.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/storage_partition_impl.h" @@ -119,17 +118,6 @@ std::move(callback))); } -void BackgroundFetchDataManager::UpdateRegistrationUI( - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon, - blink::mojom::BackgroundFetchService::UpdateUICallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - AddDatabaseTask(std::make_unique<background_fetch::UpdateRegistrationUITask>( - this, registration_id, title, icon, std::move(callback))); -} - void BackgroundFetchDataManager::PopNextRequest( const BackgroundFetchRegistrationId& registration_id, NextRequestCallback callback) {
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h index d664316..9ea199e 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.h +++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -57,8 +57,7 @@ // // Storage schema is documented in storage/README.md class CONTENT_EXPORT BackgroundFetchDataManager - : public BackgroundFetchScheduler::RequestProvider, - public background_fetch::DatabaseTaskHost { + : public background_fetch::DatabaseTaskHost { public: using GetInitializationDataCallback = base::OnceCallback<void( blink::mojom::BackgroundFetchError, @@ -115,13 +114,6 @@ const std::string& developer_id, GetRegistrationCallback callback); - // Updates the UI values for a Background Fetch registration. - void UpdateRegistrationUI( - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon, - blink::mojom::BackgroundFetchService::UpdateUICallback callback); - // Reads the settled fetches for the given |registration_id| based on // |match_params|. Both the Request and Response objects will be initialised // based on the stored data. Will invoke the |callback| when the list of @@ -131,6 +123,17 @@ std::unique_ptr<BackgroundFetchRequestMatchParams> match_params, SettledFetchesCallback callback); + // Retrieves the next pending request for |registration_id| and invoke + // |callback| with it. + void PopNextRequest(const BackgroundFetchRegistrationId& registration_id, + NextRequestCallback callback); + + // Marks |request_info| as complete and calls |callback| when done. + void MarkRequestAsComplete( + const BackgroundFetchRegistrationId& registration_id, + scoped_refptr<BackgroundFetchRequestInfo> request_info, + MarkRequestCompleteCallback callback); + // Marks that the // backgroundfetchsuccess/backgroundfetchfail/backgroundfetchabort event is // being dispatched. It's not possible to call DeleteRegistration at this @@ -168,14 +171,6 @@ return observers_; } - // BackgroundFetchScheduler::RequestProvider implementation: - void PopNextRequest(const BackgroundFetchRegistrationId& registration_id, - NextRequestCallback callback) override; - void MarkRequestAsComplete( - const BackgroundFetchRegistrationId& registration_id, - scoped_refptr<BackgroundFetchRequestInfo> request_info, - MarkRequestCompleteCallback callback) override; - void ShutdownOnIO(); private:
diff --git a/content/browser/background_fetch/background_fetch_data_manager_observer.h b/content/browser/background_fetch/background_fetch_data_manager_observer.h index 032cc12..4b800e4 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_observer.h +++ b/content/browser/background_fetch/background_fetch_data_manager_observer.h
@@ -6,7 +6,9 @@ #define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_DATA_MANAGER_OBSERVER_H_ #include <memory> +#include <vector> +#include "base/memory/scoped_refptr.h" #include "base/optional.h" class SkBitmap; @@ -16,6 +18,7 @@ struct BackgroundFetchOptions; struct BackgroundFetchRegistration; class BackgroundFetchRegistrationId; +class BackgroundFetchRequestInfo; // Observer interface for objects that would like to be notified about changes // committed to storage through the Background Fetch data manager. All methods @@ -31,25 +34,26 @@ int num_requests, bool start_paused) = 0; - // Called when the UI options for the Background Fetch |registration_id| have - // been updated in the data store. - virtual void OnUpdatedUI(const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon) = 0; + // Called on start-up when an incomplete registration has been found. + virtual void OnRegistrationLoadedAtStartup( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests) = 0; + + // Called when a registration is being queried. Implementations should update + // |registration| with in-progress information. + virtual void OnRegistrationQueried( + BackgroundFetchRegistration* registration) = 0; // Called if corrupted data is found in the Service Worker database. virtual void OnServiceWorkerDatabaseCorrupted( int64_t service_worker_registration_id) = 0; - // Called if the origin is out of quota during the fetch. - virtual void OnQuotaExceeded( - const BackgroundFetchRegistrationId& registration_id) = 0; - - // Called if a database task encountered a storage error in the context of a - // fetch workflow, such as preparing a request or storing a response. - virtual void OnFetchStorageError( - const BackgroundFetchRegistrationId& registration_id) = 0; - virtual ~BackgroundFetchDataManagerObserver() {} };
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc index cc2618b..1079d8ce 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc +++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -59,7 +59,6 @@ const char kAlternativeUniqueId[] = "bb48a9fb-c21f-4c2d-a9ae-58bd48a9fb53"; const char kInitialTitle[] = "Initial Title"; -const char kUpdatedTitle[] = "Updated Title"; constexpr size_t kResponseFileSize = 42u; @@ -285,22 +284,6 @@ return metadata; } - void UpdateRegistrationUI( - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& updated_title, - const base::Optional<SkBitmap>& updated_icon, - blink::mojom::BackgroundFetchError* out_error) { - DCHECK(out_error); - - base::RunLoop run_loop; - background_fetch_data_manager_->UpdateRegistrationUI( - registration_id, updated_title, updated_icon, - base::BindOnce(&BackgroundFetchDataManagerTest::DidUpdateRegistrationUI, - base::Unretained(this), run_loop.QuitClosure(), - out_error)); - run_loop.Run(); - } - std::vector<std::string> GetDeveloperIds( int64_t service_worker_registration_id, const url::Origin& origin, @@ -579,16 +562,19 @@ const SkBitmap& icon, int num_requests, bool start_paused)); - MOCK_METHOD3(OnUpdatedUI, - void(const BackgroundFetchRegistrationId& registration, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon)); + MOCK_METHOD7(OnRegistrationLoadedAtStartup, + void(const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests)); + MOCK_METHOD1(OnRegistrationQueried, + void(BackgroundFetchRegistration* registration)); MOCK_METHOD1(OnServiceWorkerDatabaseCorrupted, void(int64_t service_worker_registration_id)); - MOCK_METHOD1(OnQuotaExceeded, - void(const BackgroundFetchRegistrationId& registration_id)); - MOCK_METHOD1(OnFetchStorageError, - void(const BackgroundFetchRegistrationId& registration_id)); protected: void DidGetRegistration(base::OnceClosure quit_closure, @@ -618,13 +604,6 @@ std::move(quit_closure).Run(); } - void DidUpdateRegistrationUI(base::OnceClosure quit_closure, - blink::mojom::BackgroundFetchError* out_error, - blink::mojom::BackgroundFetchError error) { - *out_error = error; - std::move(quit_closure).Run(); - } - void DidGetDeveloperIds(base::Closure quit_closure, blink::mojom::BackgroundFetchError* out_error, std::vector<std::string>* out_ids, @@ -1039,109 +1018,6 @@ EXPECT_TRUE(GetUIOptions(sw_id).second.isNull()); } -TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) { - int64_t sw_id = RegisterServiceWorker(); - ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id); - - BackgroundFetchRegistrationId registration_id( - sw_id, origin(), kExampleDeveloperId, kExampleUniqueId); - - std::vector<ServiceWorkerFetchRequest> requests = - CreateValidRequests(origin(), 2u); - BackgroundFetchOptions options; - options.title = kInitialTitle; - blink::mojom::BackgroundFetchError error; - - // There should be no title before the registration. - EXPECT_TRUE(GetUIOptions(sw_id).first.empty()); - - // Create a single registration. - { - EXPECT_CALL(*this, OnRegistrationCreated(registration_id, _, _, _, _, _)); - - CreateRegistration(registration_id, requests, options, CreateTestIcon(), - &error); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - } - - // Verify that the UI Options can be retrieved. - { - auto ui_options = GetUIOptions(sw_id); - EXPECT_EQ(ui_options.first, kInitialTitle); - EXPECT_NO_FATAL_FAILURE( - ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN)); - } - - // Update only the title. - { - EXPECT_CALL(*this, - OnUpdatedUI(registration_id, - base::Optional<std::string>(kUpdatedTitle), _)); - - UpdateRegistrationUI(registration_id, kUpdatedTitle, base::nullopt, &error); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - - auto ui_options = GetUIOptions(sw_id); - // Expect new title. - EXPECT_EQ(ui_options.first, kUpdatedTitle); - // Expect same icon as before. - EXPECT_NO_FATAL_FAILURE( - ExpectIconProperties(ui_options.second, 42, SK_ColorGREEN)); - } - - // Update only the icon. - { - EXPECT_CALL(*this, OnUpdatedUI(registration_id, _, _)); - - UpdateRegistrationUI(registration_id, base::nullopt, - CreateTestIcon(24 /* size */), &error); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - - auto ui_options = GetUIOptions(sw_id); - // Expect the same title as before. - EXPECT_EQ(ui_options.first, kUpdatedTitle); - // Expect the new icon with the different size. - EXPECT_NO_FATAL_FAILURE( - ExpectIconProperties(ui_options.second, 24, SK_ColorGREEN)); - } - - // Update both the title and icon. - { - EXPECT_CALL(*this, - OnUpdatedUI(registration_id, - base::Optional<std::string>(kInitialTitle), _)); - - UpdateRegistrationUI(registration_id, kInitialTitle, - CreateTestIcon(66 /* size */), &error); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - - auto ui_options = GetUIOptions(sw_id); - // Expect the initial title again. - EXPECT_EQ(ui_options.first, kInitialTitle); - // Expect the new icon with the different size. - EXPECT_NO_FATAL_FAILURE( - ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN)); - } - - // New title and an icon that's too large. - { - EXPECT_CALL(*this, - OnUpdatedUI(registration_id, - base::Optional<std::string>(kUpdatedTitle), _)); - - UpdateRegistrationUI(registration_id, kUpdatedTitle, - CreateTestIcon(512 /* size */), &error); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - - auto ui_options = GetUIOptions(sw_id); - // Expect the new title. - EXPECT_EQ(ui_options.first, kUpdatedTitle); - // Expect same icon as before. - EXPECT_NO_FATAL_FAILURE( - ExpectIconProperties(ui_options.second, 66, SK_ColorGREEN)); - } -} - TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) { int64_t sw_id = RegisterServiceWorker(); ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id); @@ -1466,7 +1342,7 @@ EXPECT_EQ(registration.downloaded, 2 * kResponseFileSize); } -TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaAbandonsFetch) { +TEST_F(BackgroundFetchDataManagerTest, ExceedingQuotaIsReported) { int64_t sw_id = RegisterServiceWorker(); ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id); @@ -1488,11 +1364,8 @@ ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); AnnotateRequestInfoWithFakeDownloadManagerData( request_info.get(), true /* succeeded */, true /* over_quota */); - { - EXPECT_CALL(*this, OnQuotaExceeded(registration_id)); - MarkRequestAsComplete(registration_id, request_info.get(), &error); - EXPECT_EQ(error, blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED); - } + MarkRequestAsComplete(registration_id, request_info.get(), &error); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED); } TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc index 153d041..ba23fc4 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc +++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -401,7 +401,7 @@ JobDetails& job_details = job_details_iter->second; if (job_details.controller) - job_details.controller->Abort(reason_to_abort); + job_details.controller->AbortFromDelegate(reason_to_abort); } void BackgroundFetchDelegateProxy::DidStartRequest(
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.h b/content/browser/background_fetch/background_fetch_delegate_proxy.h index e877ab6..0a9f94b7 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy.h +++ b/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -49,7 +49,8 @@ const scoped_refptr<BackgroundFetchRequestInfo>& request) = 0; // Called when the delegate aborts a Background Fetch registration. - virtual void Abort(blink::mojom::BackgroundFetchFailureReason) = 0; + virtual void AbortFromDelegate( + blink::mojom::BackgroundFetchFailureReason) = 0; virtual ~Controller() {} };
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc index b5b5e2e..9f0b03d 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc +++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -129,7 +129,7 @@ request_completed_ = true; } - void Abort( + void AbortFromDelegate( blink::mojom::BackgroundFetchFailureReason reason_to_abort) override {} bool request_started_ = false;
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/content/browser/background_fetch/background_fetch_event_dispatcher.cc index caa02e975..87765c9 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -75,6 +75,41 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); } +void BackgroundFetchEventDispatcher::DispatchBackgroundFetchCompletionEvent( + const BackgroundFetchRegistrationId& registration_id, + std::unique_ptr<BackgroundFetchRegistration> registration, + base::OnceClosure finished_closure) { + switch (registration->failure_reason) { + case blink::mojom::BackgroundFetchFailureReason::NONE: + DCHECK_EQ(registration->result, + blink::mojom::BackgroundFetchResult::SUCCESS); + DispatchBackgroundFetchSuccessEvent(registration_id, + std::move(registration), + std::move(finished_closure)); + return; + case blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI: + case blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER: + DCHECK_EQ(registration->result, + blink::mojom::BackgroundFetchResult::FAILURE); + DispatchBackgroundFetchAbortEvent(registration_id, + std::move(registration), + std::move(finished_closure)); + return; + case blink::mojom::BackgroundFetchFailureReason::BAD_STATUS: + case blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR: + case blink::mojom::BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE: + case blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED: + case blink::mojom::BackgroundFetchFailureReason:: + TOTAL_DOWNLOAD_SIZE_EXCEEDED: + DCHECK_EQ(registration->result, + blink::mojom::BackgroundFetchResult::FAILURE); + DispatchBackgroundFetchFailEvent(registration_id, std::move(registration), + std::move(finished_closure)); + return; + } + NOTREACHED(); +} + void BackgroundFetchEventDispatcher::DispatchBackgroundFetchAbortEvent( const BackgroundFetchRegistrationId& registration_id, std::unique_ptr<BackgroundFetchRegistration> registration,
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher.h b/content/browser/background_fetch/background_fetch_event_dispatcher.h index 4ab631be..8e7ba89 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher.h +++ b/content/browser/background_fetch/background_fetch_event_dispatcher.h
@@ -40,9 +40,9 @@ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context); ~BackgroundFetchEventDispatcher(); - // Dispatches the `backgroundfetchabort` event, which indicates that an active - // background fetch was aborted by the user or another external event. - void DispatchBackgroundFetchAbortEvent( + // Dispatches one of the update, fail, or success events depending on the + // provided registration. + void DispatchBackgroundFetchCompletionEvent( const BackgroundFetchRegistrationId& registration_id, std::unique_ptr<BackgroundFetchRegistration> registration, base::OnceClosure finished_closure); @@ -54,6 +54,17 @@ std::unique_ptr<BackgroundFetchRegistration> registration, base::OnceClosure finished_closure); + private: + using ServiceWorkerLoadedCallback = + base::Callback<void(scoped_refptr<ServiceWorkerVersion>, int request_id)>; + + // Dispatches the `backgroundfetchabort` event, which indicates that an active + // background fetch was aborted by the user or another external event. + void DispatchBackgroundFetchAbortEvent( + const BackgroundFetchRegistrationId& registration_id, + std::unique_ptr<BackgroundFetchRegistration> registration, + base::OnceClosure finished_closure); + // Dispatches the `backgroundfetchfail` event, which indicates that a // background fetch has finished with one or more failed fetches. void DispatchBackgroundFetchFailEvent( @@ -68,10 +79,6 @@ std::unique_ptr<BackgroundFetchRegistration> registration, base::OnceClosure finished_closure); - private: - using ServiceWorkerLoadedCallback = - base::Callback<void(scoped_refptr<ServiceWorkerVersion>, int)>; - // Phase at which the dispatching process finished. Used for UMA. enum class DispatchPhase { FINDING, STARTING, DISPATCHING };
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc index d897cb81..efe53279 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher_unittest.cc
@@ -49,8 +49,8 @@ invalid_registration_id.developer_id(), invalid_registration_id.unique_id(), blink::mojom::BackgroundFetchResult::FAILURE, - blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED); - event_dispatcher_.DispatchBackgroundFetchAbortEvent( + blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER); + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( invalid_registration_id, std::move(registration), run_loop.QuitClosure()); run_loop.Run(); @@ -81,7 +81,7 @@ kExampleDeveloperId, kExampleUniqueId, blink::mojom::BackgroundFetchResult::FAILURE, blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI); - event_dispatcher_.DispatchBackgroundFetchAbortEvent( + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( registration_id, std::move(registration), run_loop.QuitClosure()); run_loop.Run(); @@ -110,10 +110,10 @@ auto registration = CreateBackgroundFetchRegistration( kExampleDeveloperId2, kExampleUniqueId2, blink::mojom::BackgroundFetchResult::FAILURE, - blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED); - event_dispatcher_.DispatchBackgroundFetchAbortEvent(second_registration_id, - std::move(registration), - run_loop.QuitClosure()); + blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER); + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( + second_registration_id, std::move(registration), + run_loop.QuitClosure()); run_loop.Run(); } @@ -217,7 +217,7 @@ kExampleDeveloperId, kExampleUniqueId, blink::mojom::BackgroundFetchResult::FAILURE, blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED); - event_dispatcher_.DispatchBackgroundFetchFailEvent( + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( registration_id, std::move(registration), run_loop.QuitClosure()); run_loop.Run(); @@ -243,9 +243,9 @@ kExampleDeveloperId2, kExampleUniqueId2, blink::mojom::BackgroundFetchResult::FAILURE, blink::mojom::BackgroundFetchFailureReason::QUOTA_EXCEEDED); - event_dispatcher_.DispatchBackgroundFetchFailEvent(second_registration_id, - std::move(registration), - run_loop.QuitClosure()); + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( + second_registration_id, std::move(registration), + run_loop.QuitClosure()); run_loop.Run(); } @@ -279,7 +279,7 @@ kExampleDeveloperId, kExampleUniqueId, blink::mojom::BackgroundFetchResult::SUCCESS, blink::mojom::BackgroundFetchFailureReason::NONE); - event_dispatcher_.DispatchBackgroundFetchSuccessEvent( + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( registration_id, std::move(registration), run_loop.QuitClosure()); run_loop.Run(); @@ -308,7 +308,7 @@ kExampleDeveloperId2, kExampleUniqueId2, blink::mojom::BackgroundFetchResult::SUCCESS, blink::mojom::BackgroundFetchFailureReason::NONE); - event_dispatcher_.DispatchBackgroundFetchSuccessEvent( + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( second_registration_id, std::move(registration), run_loop.QuitClosure());
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc index a0e07e4..55f1f53 100644 --- a/content/browser/background_fetch/background_fetch_job_controller.cc +++ b/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "content/browser/background_fetch/background_fetch_job_controller.h" +#include "content/browser/background_fetch/background_fetch_data_manager.h" #include "content/public/common/origin_util.h" #include "services/network/public/cpp/cors/cors.h" #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h" @@ -13,25 +14,72 @@ namespace content { +namespace { + +// Performs mixed content checks on the |request| for Background Fetch. +// Background Fetch depends on Service Workers, which are restricted for use +// on secure origins. We can therefore assume that the registration's origin +// is secure. This test ensures that the origin for the url of every +// request is also secure. +bool IsMixedContent(const BackgroundFetchRequestInfo& request) { + // Empty request is valid, it shouldn't fail the mixed content check. + if (request.fetch_request().url.is_empty()) + return false; + + return !IsOriginSecure(request.fetch_request().url); +} + +// Whether the |request| needs CORS preflight. +// Requests that require CORS preflights are temporarily blocked, because the +// browser side of Background Fetch doesn't yet support performing CORS +// checks. TODO(crbug.com/711354): Remove this temporary block. +bool RequiresCORSPreflight(const BackgroundFetchRequestInfo& request, + const url::Origin& origin) { + auto fetch_request = request.fetch_request(); + + // Same origin requests don't require a CORS preflight. + // https://fetch.spec.whatwg.org/#main-fetch + // TODO(crbug.com/711354): Make sure that cross-origin redirects are disabled. + if (url::IsSameOriginWith(origin.GetURL(), fetch_request.url)) + return false; + + // Requests that are more involved than what is possible with HTML's form + // element require a CORS-preflight request. + // https://fetch.spec.whatwg.org/#main-fetch + if (!fetch_request.method.empty() && + !network::cors::IsCORSSafelistedMethod(fetch_request.method)) { + return true; + } + + net::HttpRequestHeaders::HeaderVector headers; + for (const auto& header : fetch_request.headers) + headers.emplace_back(header.first, header.second); + + return !network::cors::CORSUnsafeRequestHeaderNames(headers).empty(); +} + +} // namespace + +using blink::mojom::BackgroundFetchError; using blink::mojom::BackgroundFetchFailureReason; BackgroundFetchJobController::BackgroundFetchJobController( + BackgroundFetchDataManager* data_manager, BackgroundFetchDelegateProxy* delegate_proxy, - BackgroundFetchScheduler* scheduler, const BackgroundFetchRegistrationId& registration_id, const BackgroundFetchOptions& options, const SkBitmap& icon, uint64_t bytes_downloaded, ProgressCallback progress_callback, - BackgroundFetchScheduler::FinishedCallback finished_callback) - : BackgroundFetchScheduler::Controller(scheduler, - registration_id, - std::move(finished_callback)), + FinishedCallback finished_callback) + : data_manager_(data_manager), + delegate_proxy_(delegate_proxy), + registration_id_(registration_id), options_(options), icon_(icon), complete_requests_downloaded_bytes_cache_(bytes_downloaded), - delegate_proxy_(delegate_proxy), progress_callback_(std::move(progress_callback)), + finished_callback_(std::move(finished_callback)), weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::IO); } @@ -41,7 +89,6 @@ int total_downloads, std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_fetch_requests, - const std::string& ui_title, bool start_paused) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -49,7 +96,6 @@ DCHECK_GT(total_downloads, 0); DCHECK_EQ(total_downloads_, 0); - outstanding_requests_ = active_fetch_requests; completed_downloads_ = completed_downloads; total_downloads_ = total_downloads; @@ -62,7 +108,7 @@ active_guids.push_back(request_info->download_guid()); auto fetch_description = std::make_unique<BackgroundFetchDescription>( - registration_id().unique_id(), ui_title, registration_id().origin(), + registration_id().unique_id(), options_.title, registration_id().origin(), icon_, completed_downloads, total_downloads, complete_requests_downloaded_bytes_cache_, total_downloads_size_, std::move(active_guids), start_paused); @@ -79,41 +125,6 @@ return completed_downloads_ < total_downloads_; } -bool BackgroundFetchJobController::IsMixedContent( - const BackgroundFetchRequestInfo& request) { - // Empty request is valid, it shouldn't fail the mixed content check. - if (request.fetch_request().url.is_empty()) - return false; - - return !IsOriginSecure(request.fetch_request().url); -} - -bool BackgroundFetchJobController::RequiresCORSPreflight( - const BackgroundFetchRequestInfo& request) { - auto fetch_request = request.fetch_request(); - - // Same origin requests don't require a CORS preflight. - // https://fetch.spec.whatwg.org/#main-fetch - // TODO(crbug.com/711354): Make sure that cross-origin redirects are disabled. - if (url::IsSameOriginWith(registration_id().origin().GetURL(), - fetch_request.url)) { - return false; - } - - // Requests that are more involved than what is possible with HTML's form - // element require a CORS-preflight request. - // https://fetch.spec.whatwg.org/#main-fetch - if (!fetch_request.method.empty() && - !network::cors::IsCORSSafelistedMethod(fetch_request.method)) { - return true; - } - - net::HttpRequestHeaders::HeaderVector headers; - for (const auto& header : fetch_request.headers) - headers.emplace_back(header.first, header.second); - return !network::cors::CORSUnsafeRequestHeaderNames(headers).empty(); -} - void BackgroundFetchJobController::StartRequest( scoped_refptr<BackgroundFetchRequestInfo> request, RequestFinishedCallback request_finished_callback) { @@ -125,7 +136,8 @@ active_request_downloaded_bytes_ = 0; active_request_finished_callback_ = std::move(request_finished_callback); - if (IsMixedContent(*request.get()) || RequiresCORSPreflight(*request.get())) { + if (IsMixedContent(*request.get()) || + RequiresCORSPreflight(*request.get(), registration_id_.origin())) { request->SetEmptyResultWithFailureReason( BackgroundFetchResult::FailureReason::FETCH_ERROR); @@ -138,11 +150,6 @@ registration_id().origin(), request); } -std::vector<scoped_refptr<BackgroundFetchRequestInfo>> -BackgroundFetchJobController::TakeOutstandingRequests() { - return std::move(outstanding_requests_); -} - void BackgroundFetchJobController::DidStartRequest( const scoped_refptr<BackgroundFetchRequestInfo>& request) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -162,8 +169,7 @@ active_request_downloaded_bytes_ = bytes_downloaded; - auto registration = - NewRegistration(blink::mojom::BackgroundFetchResult::UNSET); + auto registration = NewRegistration(); registration->downloaded += GetInProgressDownloadedBytes(); progress_callback_.Run(*registration); } @@ -186,45 +192,107 @@ std::move(active_request_finished_callback_).Run(request); } -void BackgroundFetchJobController::UpdateUI( - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - delegate_proxy_->UpdateUI(registration_id().unique_id(), title, icon); -} - std::unique_ptr<BackgroundFetchRegistration> -BackgroundFetchJobController::NewRegistration( - blink::mojom::BackgroundFetchResult result) const { +BackgroundFetchJobController::NewRegistration() const { return std::make_unique<BackgroundFetchRegistration>( registration_id().developer_id(), registration_id().unique_id(), 0 /* upload_total */, 0 /* uploaded */, total_downloads_size_, - complete_requests_downloaded_bytes_cache_, result, failure_reason_); + complete_requests_downloaded_bytes_cache_, + blink::mojom::BackgroundFetchResult::UNSET, failure_reason_); } uint64_t BackgroundFetchJobController::GetInProgressDownloadedBytes() { return active_request_downloaded_bytes_; } -void BackgroundFetchJobController::Abort( +void BackgroundFetchJobController::AbortFromDelegate( BackgroundFetchFailureReason failure_reason) { failure_reason_ = failure_reason; // Stop propagating any in-flight events to the scheduler. active_request_finished_callback_.Reset(); + Finish(failure_reason_, base::DoNothing()); +} + +void BackgroundFetchJobController::Abort( + BackgroundFetchFailureReason failure_reason, + ErrorCallback callback) { + failure_reason_ = failure_reason; + + // Stop propagating any in-flight events to the scheduler. + active_request_finished_callback_.Reset(); + // Cancel any in-flight downloads and UI through the BGFetchDelegate. delegate_proxy_->Abort(registration_id().unique_id()); - Finish(failure_reason_); + Finish(failure_reason_, std::move(callback)); } -BackgroundFetchFailureReason BackgroundFetchJobController::MergeFailureReason( - BackgroundFetchFailureReason failure_reason) { - if (failure_reason_ == BackgroundFetchFailureReason::NONE) - failure_reason_ = failure_reason; - return failure_reason_; +void BackgroundFetchJobController::Finish( + BackgroundFetchFailureReason reason_to_abort, + ErrorCallback callback) { + DCHECK(reason_to_abort != BackgroundFetchFailureReason::NONE || + !HasMoreRequests()); + + // Race conditions make it possible for a controller to finish twice. This + // should be removed when the scheduler starts owning the controllers. + if (!finished_callback_) { + std::move(callback).Run(BackgroundFetchError::INVALID_ID); + return; + } + + std::move(finished_callback_) + .Run(registration_id_, reason_to_abort, std::move(callback)); +} + +void BackgroundFetchJobController::DidPopNextRequest( + BackgroundFetchError error, + scoped_refptr<BackgroundFetchRequestInfo> request_info) { + if (error != BackgroundFetchError::NONE) { + Abort(BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE, + base::DoNothing()); + return; + } + + StartRequest( + std::move(request_info), + base::BindOnce(&BackgroundFetchJobController::MarkRequestAsComplete, + GetWeakPtr())); +} + +void BackgroundFetchJobController::MarkRequestAsComplete( + scoped_refptr<BackgroundFetchRequestInfo> request_info) { + data_manager_->MarkRequestAsComplete( + registration_id(), std::move(request_info), + base::BindOnce(&BackgroundFetchJobController::DidMarkRequestAsComplete, + GetWeakPtr())); +} + +void BackgroundFetchJobController::DidMarkRequestAsComplete( + BackgroundFetchError error) { + switch (error) { + case BackgroundFetchError::NONE: + break; + case BackgroundFetchError::STORAGE_ERROR: + Abort(BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE, + base::DoNothing()); + return; + case BackgroundFetchError::QUOTA_EXCEEDED: + Abort(BackgroundFetchFailureReason::QUOTA_EXCEEDED, base::DoNothing()); + return; + default: + NOTREACHED(); + } + + if (HasMoreRequests()) { + data_manager_->PopNextRequest( + registration_id(), + base::BindOnce(&BackgroundFetchJobController::DidPopNextRequest, + GetWeakPtr())); + return; + } + Finish(BackgroundFetchFailureReason::NONE, base::DoNothing()); } } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h index ab829c8..84cd80c 100644 --- a/content/browser/background_fetch/background_fetch_job_controller.h +++ b/content/browser/background_fetch/background_fetch_job_controller.h
@@ -26,6 +26,8 @@ namespace content { +class BackgroundFetchDataManager; + // The JobController will be responsible for coordinating communication with the // DownloadManager. It will get requests from the RequestManager and dispatch // them to the DownloadService. It lives entirely on the IO thread. @@ -35,25 +37,29 @@ // DownloadService or Offline Items Collection is necessary (i.e. once the // registration has been aborted, or once it has completed/failed and the // waitUntil promise has been resolved so UpdateUI can no longer be called). -class CONTENT_EXPORT BackgroundFetchJobController final - : public BackgroundFetchDelegateProxy::Controller, - public BackgroundFetchScheduler::Controller { +class CONTENT_EXPORT BackgroundFetchJobController + : public BackgroundFetchDelegateProxy::Controller { public: + using ErrorCallback = + base::OnceCallback<void(blink::mojom::BackgroundFetchError)>; using FinishedCallback = base::OnceCallback<void(const BackgroundFetchRegistrationId&, - blink::mojom::BackgroundFetchFailureReason)>; + blink::mojom::BackgroundFetchFailureReason, + ErrorCallback)>; using ProgressCallback = base::RepeatingCallback<void(const BackgroundFetchRegistration&)>; + using RequestFinishedCallback = + base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>; BackgroundFetchJobController( + BackgroundFetchDataManager* data_manager, BackgroundFetchDelegateProxy* delegate_proxy, - BackgroundFetchScheduler* scheduler, const BackgroundFetchRegistrationId& registration_id, const BackgroundFetchOptions& options, const SkBitmap& icon, uint64_t bytes_downloaded, ProgressCallback progress_callback, - BackgroundFetchScheduler::FinishedCallback finished_callback); + FinishedCallback finished_callback); ~BackgroundFetchJobController() override; // Initializes the job controller with the status of the active and completed @@ -64,21 +70,14 @@ int total_downloads, std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_fetch_requests, - const std::string& ui_title, bool start_paused); // Gets the number of bytes downloaded for jobs that are currently running. uint64_t GetInProgressDownloadedBytes(); - // Updates the UI that's shown to the user as part of a notification for - // instance. - void UpdateUI(const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon); - // Returns a unique_ptr to a BackgroundFetchRegistration object // created with member fields. - std::unique_ptr<BackgroundFetchRegistration> NewRegistration( - blink::mojom::BackgroundFetchResult result) const; + std::unique_ptr<BackgroundFetchRegistration> NewRegistration() const; // Returns the options with which this job is fetching data. const BackgroundFetchOptions& options() const { return options_; } @@ -92,10 +91,9 @@ // Returns the number of requests that comprise the whole job. int total_downloads() const { return total_downloads_; } - // If |failure_reason_| is none, overwrites it with |failure_reason|, and - // returns the new value. - blink::mojom::BackgroundFetchFailureReason MergeFailureReason( - blink::mojom::BackgroundFetchFailureReason failure_reason); + const BackgroundFetchRegistrationId& registration_id() const { + return registration_id_; + } base::WeakPtr<BackgroundFetchJobController> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); @@ -109,29 +107,46 @@ uint64_t bytes_downloaded) override; void DidCompleteRequest( const scoped_refptr<BackgroundFetchRequestInfo>& request) override; - - // BackgroundFetchScheduler::Controller implementation: - bool HasMoreRequests() override; - void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request, - RequestFinishedCallback request_finished_callback) override; - std::vector<scoped_refptr<BackgroundFetchRequestInfo>> - TakeOutstandingRequests() override; - void Abort( + void AbortFromDelegate( blink::mojom::BackgroundFetchFailureReason failure_reason) override; - private: - // Performs mixed content checks on the |request| for Background Fetch. - // Background Fetch depends on Service Workers, which are restricted for use - // on secure origins. We can therefore assume that the registration's origin - // is secure. This test ensures that the origin for the url of every - // request is also secure. - bool IsMixedContent(const BackgroundFetchRequestInfo& request); + // Aborts the fetch. |callback| will run with the result of marking the + // registration for deletion. + void Abort(blink::mojom::BackgroundFetchFailureReason failure_reason, + ErrorCallback callback); - // Whether the |request| needs CORS preflight. - // Requests that require CORS preflights are temporarily blocked, because the - // browser side of Background Fetch doesn't yet support performing CORS - // checks. TODO(crbug.com/711354): Remove this temporary block. - bool RequiresCORSPreflight(const BackgroundFetchRequestInfo& request); + // Request processing callbacks. + void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request, + RequestFinishedCallback request_finished_callback); + void DidPopNextRequest( + blink::mojom::BackgroundFetchError error, + scoped_refptr<BackgroundFetchRequestInfo> request_info); + void MarkRequestAsComplete( + scoped_refptr<BackgroundFetchRequestInfo> request_info); + + private: + // Called after the request is completely processed, and the next one can be + // started. + void DidMarkRequestAsComplete(blink::mojom::BackgroundFetchError error); + + // Whether there are more requests to process as part of this job. + bool HasMoreRequests(); + + // Called when the job completes or has been aborted. |callback| will run + // with the result of marking the registration for deletion. + void Finish(blink::mojom::BackgroundFetchFailureReason reason_to_abort, + ErrorCallback callback); + + // Manager for interacting with the DB. It is owned by the + // BackgroundFetchContext. + BackgroundFetchDataManager* data_manager_; + + // Proxy for interacting with the BackgroundFetchDelegate across thread + // boundaries. It is owned by the BackgroundFetchContext. + BackgroundFetchDelegateProxy* delegate_proxy_; + + // The registration ID of the fetch this controller represents. + BackgroundFetchRegistrationId registration_id_; // Options for the represented background fetch registration. BackgroundFetchOptions options_; @@ -139,10 +154,6 @@ // Icon for the represented background fetch registration. SkBitmap icon_; - // The list of requests for this fetch that started in a previous session - // and did not finish. - std::vector<scoped_refptr<BackgroundFetchRequestInfo>> outstanding_requests_; - // Number of bytes downloaded for the active request. uint64_t active_request_downloaded_bytes_ = 0; @@ -156,10 +167,6 @@ // Total downloads size, as indicated by the developer. int total_downloads_size_ = 0; - // Proxy for interacting with the BackgroundFetchDelegate across thread - // boundaries. It is owned by the BackgroundFetchContext. - BackgroundFetchDelegateProxy* delegate_proxy_; - // Callback run each time download progress updates. ProgressCallback progress_callback_; @@ -173,6 +180,9 @@ blink::mojom::BackgroundFetchFailureReason failure_reason_ = blink::mojom::BackgroundFetchFailureReason::NONE; + // Custom callback that runs after the controller is finished. + FinishedCallback finished_callback_; + base::WeakPtrFactory<BackgroundFetchJobController> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BackgroundFetchJobController);
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc index 259b466..38d116c 100644 --- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc +++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -146,7 +146,7 @@ delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>(delegate_); auto controller = std::make_unique<BackgroundFetchJobController>( - delegate_proxy_.get(), context_->scheduler_.get(), registration_id, + nullptr /* data_manager */, delegate_proxy_.get(), registration_id, BackgroundFetchOptions(), SkBitmap(), 0 /* bytes_downloaded */, base::BindRepeating( &BackgroundFetchJobControllerTest::DidUpdateProgress, @@ -154,17 +154,17 @@ base::BindOnce(&BackgroundFetchJobControllerTest::DidFinishJob, base::Unretained(this))); - controller->InitializeRequestStatus( - 0, total_downloads, {} /* outstanding_guids */, "" /* ui_title */, - /* start_paused = */ false); + controller->InitializeRequestStatus(0, total_downloads, + {} /* outstanding_guids */, + /* start_paused = */ false); return controller; } - void AddControllerToContextMap( + void AddControllerToSchedulerMap( const std::string& unique_id, std::unique_ptr<BackgroundFetchJobController> controller) { - context_->job_controllers_[unique_id] = std::move(controller); + scheduler()->job_controllers_[unique_id] = std::move(controller); } // BackgroundFetchTestBase overrides: @@ -206,6 +206,8 @@ std::unique_ptr<BackgroundFetchDelegateProxy> delegate_proxy_; BackgroundFetchDelegate* delegate_; + BackgroundFetchScheduler* scheduler() { return context_->scheduler_.get(); } + private: void DidUpdateProgress(const BackgroundFetchRegistration& registration) { last_downloaded_ = registration.downloaded; @@ -216,7 +218,8 @@ void DidFinishJob( const BackgroundFetchRegistrationId& registration_id, - blink::mojom::BackgroundFetchFailureReason reason_to_abort) { + blink::mojom::BackgroundFetchFailureReason reason_to_abort, + base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback) { auto iter = pending_requests_counts_.find(registration_id); DCHECK(iter != pending_requests_counts_.end()); @@ -383,7 +386,8 @@ base::Unretained(this), registration_id)); controller->Abort( - blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI); + blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI, + base::DoNothing()); base::RunLoop().RunUntilIdle(); @@ -440,9 +444,10 @@ std::unique_ptr<BackgroundFetchJobController> controller = CreateJobController(registration_id, requests.size()); - AddControllerToContextMap(registration_id.unique_id(), std::move(controller)); - context_->OnRegistrationDeleted(kExampleServiceWorkerRegistrationId, - GURL("https://example.com/funny_cat.png")); + AddControllerToSchedulerMap(registration_id.unique_id(), + std::move(controller)); + scheduler()->OnRegistrationDeleted(kExampleServiceWorkerRegistrationId, + GURL("https://example.com/funny_cat.png")); base::RunLoop().RunUntilIdle(); @@ -463,9 +468,10 @@ std::unique_ptr<BackgroundFetchJobController> controller = CreateJobController(registration_id, requests.size()); - AddControllerToContextMap(registration_id.unique_id(), std::move(controller)); + AddControllerToSchedulerMap(registration_id.unique_id(), + std::move(controller)); - context_->OnStorageWiped(); + scheduler()->OnStorageWiped(); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/background_fetch/background_fetch_metrics.cc b/content/browser/background_fetch/background_fetch_metrics.cc index 430b46f..3fc8c20 100644 --- a/content/browser/background_fetch/background_fetch_metrics.cc +++ b/content/browser/background_fetch/background_fetch_metrics.cc
@@ -19,18 +19,6 @@ // Exponential bucket spacing for UKM event data. const double kUkmEventDataBucketSpacing = 2.0; -void RecordSchedulerFinishedError(blink::mojom::BackgroundFetchError error) { - UMA_HISTOGRAM_ENUMERATION("BackgroundFetch.SchedulerFinishedError", error); -} - -void RecordRegistrationCreatedError(blink::mojom::BackgroundFetchError error) { - UMA_HISTOGRAM_ENUMERATION("BackgroundFetch.RegistrationCreatedError", error); -} - -void RecordRegistrationDeletedError(blink::mojom::BackgroundFetchError error) { - UMA_HISTOGRAM_ENUMERATION("BackgroundFetch.RegistrationDeletedError", error); -} - void RecordRegistrationsOnStartup(int num_registrations) { UMA_HISTOGRAM_COUNTS_100("BackgroundFetch.IncompleteFetchesOnStartup", num_registrations);
diff --git a/content/browser/background_fetch/background_fetch_metrics.h b/content/browser/background_fetch/background_fetch_metrics.h index 27f65916..4de20a2 100644 --- a/content/browser/background_fetch/background_fetch_metrics.h +++ b/content/browser/background_fetch/background_fetch_metrics.h
@@ -12,19 +12,6 @@ namespace background_fetch { -// Records the |error| status issued by the DataManager after it was requested -// to mark a Background Fetch registration for deletion. The marking is invoked -// by the scheduler controller after it is finished. -void RecordSchedulerFinishedError(blink::mojom::BackgroundFetchError error); - -// Records the |error| status issued by the DataManager after it was requested -// to create and store a new Background Fetch registration. -void RecordRegistrationCreatedError(blink::mojom::BackgroundFetchError error); - -// Records the |error| status issued by the DataManager after the storage -// associated with a registration has been completely deleted. -void RecordRegistrationDeletedError(blink::mojom::BackgroundFetchError error); - // Records the number of registrations that have unfinished fetches found on // start-up. void RecordRegistrationsOnStartup(int num_registrations);
diff --git a/content/browser/background_fetch/background_fetch_scheduler.cc b/content/browser/background_fetch/background_fetch_scheduler.cc index 6038067c..68a565be 100644 --- a/content/browser/background_fetch/background_fetch_scheduler.cc +++ b/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -5,167 +5,331 @@ #include "content/browser/background_fetch/background_fetch_scheduler.h" #include "base/guid.h" +#include "content/browser/background_fetch/background_fetch_data_manager.h" +#include "content/browser/background_fetch/background_fetch_delegate_proxy.h" #include "content/browser/background_fetch/background_fetch_job_controller.h" +#include "content/browser/background_fetch/background_fetch_metrics.h" +#include "content/browser/background_fetch/background_fetch_registration_notifier.h" +#include "content/browser/service_worker/service_worker_context_core_observer.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" namespace content { -BackgroundFetchScheduler::Controller::Controller( - BackgroundFetchScheduler* scheduler, - const BackgroundFetchRegistrationId& registration_id, - FinishedCallback finished_callback) - : scheduler_(scheduler), - registration_id_(registration_id), - finished_callback_(std::move(finished_callback)) { - DCHECK(scheduler_); - DCHECK(finished_callback_); -} - -BackgroundFetchScheduler::Controller::~Controller() = default; - -void BackgroundFetchScheduler::Controller::Finish( - blink::mojom::BackgroundFetchFailureReason reason_to_abort) { - DCHECK(reason_to_abort != blink::mojom::BackgroundFetchFailureReason::NONE || - !HasMoreRequests()); - - scheduler_->RemoveJobController(this); - - // Developer-initiated abortions will have already marked the registration for - // deletion, so make sure that we don't execute the same code-path twice. - if (reason_to_abort == - blink::mojom::BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER) { - return; - } - - // Race conditions make it possible for a controller to finish twice. This - // should be removed when the scheduler starts owning the controllers. - if (!finished_callback_) - return; - - std::move(finished_callback_).Run(registration_id_, reason_to_abort); -} +using blink::mojom::BackgroundFetchError; +using blink::mojom::BackgroundFetchFailureReason; BackgroundFetchScheduler::BackgroundFetchScheduler( - RequestProvider* request_provider) - : request_provider_(request_provider) {} + BackgroundFetchDataManager* data_manager, + BackgroundFetchRegistrationNotifier* registration_notifier, + BackgroundFetchDelegateProxy* delegate_proxy, + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) + : data_manager_(data_manager), + registration_notifier_(registration_notifier), + delegate_proxy_(delegate_proxy), + event_dispatcher_(std::move(service_worker_context)), + weak_ptr_factory_(this) { + DCHECK(delegate_proxy_); + delegate_proxy_->SetClickEventDispatcher( + base::BindRepeating(&BackgroundFetchScheduler::DispatchClickEvent, + weak_ptr_factory_.GetWeakPtr())); +} BackgroundFetchScheduler::~BackgroundFetchScheduler() = default; -void BackgroundFetchScheduler::AddJobController(Controller* controller) { - DCHECK(controller); - controller_queue_.push_back(controller); - - std::vector<scoped_refptr<content::BackgroundFetchRequestInfo>> - outstanding_requests = controller->TakeOutstandingRequests(); - // There are active downloads from the previous session. - if (!outstanding_requests.empty()) { - // The current assumption is that there can be at most one active fetch - // at any given time. - DCHECK(!active_controller_); - DCHECK_EQ(outstanding_requests.size(), 1u); - - active_controller_ = controller; - for (auto& request_info : outstanding_requests) { - active_controller_->StartRequest( - std::move(request_info), - base::BindOnce(&BackgroundFetchScheduler::MarkRequestAsComplete, - weak_ptr_factory_.GetWeakPtr())); - } - } - - if (!active_controller_) - ScheduleDownload(); -} - -void BackgroundFetchScheduler::RemoveJobController(Controller* controller) { - DCHECK(controller); - - base::EraseIf(controller_queue_, [controller](Controller* queued_controller) { - return controller == queued_controller; - }); - - if (active_controller_ != controller) - return; - - // TODO(peter): Move cancellation of requests to the scheduler. - active_controller_ = nullptr; - - ScheduleDownload(); -} - void BackgroundFetchScheduler::ScheduleDownload() { DCHECK(!active_controller_); - if (controller_queue_.empty()) + + if (job_controllers_.empty()) return; - active_controller_ = controller_queue_.front(); - controller_queue_.pop_front(); + while (controller_ids_.size() && + !job_controllers_.count(controller_ids_.front())) { + // Remove aborted controller ids. + controller_ids_.pop_front(); + } - request_provider_->PopNextRequest( + if (controller_ids_.empty()) + return; + + std::string controller_id = controller_ids_.front(); + controller_ids_.pop_front(); + active_controller_ = job_controllers_[controller_id].get(); + + data_manager_->PopNextRequest( active_controller_->registration_id(), - base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&BackgroundFetchJobController::DidPopNextRequest, + active_controller_->GetWeakPtr())); } -void BackgroundFetchScheduler::DidPopNextRequest( - blink::mojom::BackgroundFetchError error, - scoped_refptr<BackgroundFetchRequestInfo> request_info) { - // It's possible for the |active_controller_| to have been aborted while the - // next request was being retrieved. Bail out when that happens. - if (!active_controller_) { +void BackgroundFetchScheduler::Abort( + const BackgroundFetchRegistrationId& registration_id, + BackgroundFetchFailureReason failure_reason, + blink::mojom::BackgroundFetchService::AbortCallback callback) { + DCHECK_EQ(failure_reason, + BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER); + + auto it = job_controllers_.find(registration_id.unique_id()); + if (it == job_controllers_.end()) { + std::move(callback).Run(BackgroundFetchError::INVALID_ID); + return; + } + + it->second->Abort(failure_reason, std::move(callback)); +} + +void BackgroundFetchScheduler::FinishJob( + const BackgroundFetchRegistrationId& registration_id, + BackgroundFetchFailureReason failure_reason, + base::OnceCallback<void(BackgroundFetchError)> callback) { + bool job_started = false; + if (active_controller_ && + active_controller_->registration_id() == registration_id) { + active_controller_ = nullptr; + job_started = true; + } + + data_manager_->MarkRegistrationForDeletion( + registration_id, + /* check_for_failure= */ failure_reason == + BackgroundFetchFailureReason::NONE, + base::BindOnce(&BackgroundFetchScheduler::DidMarkForDeletion, + weak_ptr_factory_.GetWeakPtr(), registration_id, + job_started, std::move(callback))); + + auto it = job_controllers_.find(registration_id.unique_id()); + if (it != job_controllers_.end()) { + completed_fetches_[it->first] = {registration_id, + it->second->NewRegistration()}; + // Destroying the controller will stop all in progress tasks. + job_controllers_.erase(it); + } + + if (!active_controller_) ScheduleDownload(); - return; - } - - if (error != blink::mojom::BackgroundFetchError::NONE) { - // This fetch is being abandoned, after which something will be scheduled. - return; - } - - DCHECK(request_info); - - // Otherwise start the |request_info| through the live Job Controller. - active_controller_->StartRequest( - std::move(request_info), - base::BindOnce(&BackgroundFetchScheduler::MarkRequestAsComplete, - weak_ptr_factory_.GetWeakPtr())); } -void BackgroundFetchScheduler::MarkRequestAsComplete( - scoped_refptr<BackgroundFetchRequestInfo> request_info) { - // It's possible for the |active_controller_| to have been aborted while the - // request was being started. Bail out in that case. - if (!active_controller_) +void BackgroundFetchScheduler::DidMarkForDeletion( + const BackgroundFetchRegistrationId& registration_id, + bool job_started, + base::OnceCallback<void(BackgroundFetchError)> callback, + BackgroundFetchError error, + BackgroundFetchFailureReason failure_reason) { + DCHECK(callback); + std::move(callback).Run(error); + + // It's normal to get INVALID_ID errors here - it means the registration was + // already inactive (marked for deletion). This happens when an abort (from + // developer or from user) races with the download completing/failing, or even + // when two aborts race. + if (error != BackgroundFetchError::NONE) return; - request_provider_->MarkRequestAsComplete( - active_controller_->registration_id(), std::move(request_info), - base::BindOnce(&BackgroundFetchScheduler::DidMarkRequestAsComplete, - weak_ptr_factory_.GetWeakPtr())); + auto it = completed_fetches_.find(registration_id.unique_id()); + DCHECK(it != completed_fetches_.end()); + + BackgroundFetchRegistration* registration = it->second.second.get(); + // Include any other failure reasons the marking for deletion may have found. + if (registration->failure_reason == BackgroundFetchFailureReason::NONE) + registration->failure_reason = failure_reason; + + registration->result = + registration->failure_reason == BackgroundFetchFailureReason::NONE + ? blink::mojom::BackgroundFetchResult::SUCCESS + : blink::mojom::BackgroundFetchResult::FAILURE; + + registration_notifier_->Notify(*registration); + + event_dispatcher_.DispatchBackgroundFetchCompletionEvent( + registration_id, + std::make_unique<BackgroundFetchRegistration>(*registration), + base::BindOnce(&BackgroundFetchScheduler::CleanupRegistration, + weak_ptr_factory_.GetWeakPtr(), registration_id)); + + if (!job_started || + registration->failure_reason == + BackgroundFetchFailureReason::CANCELLED_FROM_UI || + registration->failure_reason == + BackgroundFetchFailureReason::CANCELLED_BY_DEVELOPER) { + // No need to keep the controller around since there won't be dispatch + // events. + completed_fetches_.erase(it); + } } -void BackgroundFetchScheduler::DidMarkRequestAsComplete( - blink::mojom::BackgroundFetchError error) { - // It's possible for the |active_controller_| to have been aborted while the - // request was being marked as completed. Bail out in that case. - if (!active_controller_) - return; +void BackgroundFetchScheduler::CleanupRegistration( + const BackgroundFetchRegistrationId& registration_id) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + // Indicate to the renderer that the records for this fetch are no longer + // available. + registration_notifier_->NotifyRecordsUnavailable(registration_id.unique_id()); - if (error != blink::mojom::BackgroundFetchError::NONE) { - // This fetch is being abandoned, after which something will be scheduled. - DCHECK_EQ(error, blink::mojom::BackgroundFetchError::STORAGE_ERROR); - return; - } + // Delete the data associated with this fetch. Cache storage will keep the + // downloaded data around so long as there are references to it, and delete + // it once there is none. We don't need to do that accounting. + data_manager_->DeleteRegistration(registration_id, base::DoNothing()); +} - // Continue with the |active_controller_| while there are files pending. - if (active_controller_->HasMoreRequests()) { - request_provider_->PopNextRequest( +void BackgroundFetchScheduler::DispatchClickEvent( + const std::string& unique_id) { + // Case 1: The active fetch received a click event. + if (active_controller_ && + active_controller_->registration_id().unique_id() == unique_id) { + event_dispatcher_.DispatchBackgroundFetchClickEvent( active_controller_->registration_id(), - base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest, - weak_ptr_factory_.GetWeakPtr())); + active_controller_->NewRegistration(), base::DoNothing()); return; } - active_controller_->Finish(blink::mojom::BackgroundFetchFailureReason::NONE); + // Case 2: A completed fetch received a click event. + auto it = completed_fetches_.find(unique_id); + if (it == completed_fetches_.end()) + return; + + event_dispatcher_.DispatchBackgroundFetchClickEvent( + it->second.first, std::move(it->second.second), base::DoNothing()); + completed_fetches_.erase(unique_id); +} + +std::unique_ptr<BackgroundFetchJobController> +BackgroundFetchScheduler::CreateInitializedController( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests, + bool start_paused) { + // TODO(rayankans): Only create a controller when the fetch starts. + auto controller = std::make_unique<BackgroundFetchJobController>( + data_manager_, delegate_proxy_, registration_id, options, icon, + registration.downloaded, + // Safe because JobControllers are destroyed before RegistrationNotifier. + base::BindRepeating(&BackgroundFetchRegistrationNotifier::Notify, + base::Unretained(registration_notifier_)), + base::BindOnce(&BackgroundFetchScheduler::FinishJob, + weak_ptr_factory_.GetWeakPtr())); + + controller->InitializeRequestStatus(num_completed_requests, num_requests, + std::move(active_fetch_requests), + start_paused); + + return controller; +} + +void BackgroundFetchScheduler::OnRegistrationCreated( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_requests, + bool start_paused) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + auto controller = CreateInitializedController( + registration_id, registration, options, icon, 0 /* completed_requests */, + num_requests, {} /* active_fetch_requests */, start_paused); + + DCHECK_EQ(job_controllers_.count(registration_id.unique_id()), 0u); + job_controllers_[registration_id.unique_id()] = std::move(controller); + controller_ids_.push_back(registration_id.unique_id()); + if (!active_controller_) + ScheduleDownload(); +} + +void BackgroundFetchScheduler::OnRegistrationLoadedAtStartup( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + auto controller = CreateInitializedController( + registration_id, registration, options, icon, num_completed_requests, + num_requests, active_fetch_requests, /* start_paused= */ false); + + // The current assumption is that there can be only one active job with one + // active fetch. + DCHECK(!active_controller_); + active_controller_ = controller.get(); + job_controllers_[registration_id.unique_id()] = std::move(controller); + + DCHECK_LE(active_fetch_requests.size(), 1u); + + if (active_fetch_requests.empty()) { + DCHECK_LT(num_completed_requests, num_requests); + // Start processing the next request. + data_manager_->PopNextRequest( + active_controller_->registration_id(), + base::BindOnce(&BackgroundFetchJobController::DidPopNextRequest, + active_controller_->GetWeakPtr())); + return; + } + + for (auto& request_info : active_fetch_requests) { + active_controller_->StartRequest( + std::move(request_info), + base::BindOnce(&BackgroundFetchJobController::MarkRequestAsComplete, + active_controller_->GetWeakPtr())); + } +} + +void BackgroundFetchScheduler::AbortFetches( + int64_t service_worker_registration_id) { + // Abandon all active associated with this service worker. + // BackgroundFetchJobController::Abort() will eventually lead to deletion of + // the controller from job_controllers, so the IDs need to be copied over. + std::vector<BackgroundFetchJobController*> to_abort; + for (const auto& controller : job_controllers_) { + if (service_worker_registration_id != + blink::mojom::kInvalidServiceWorkerRegistrationId && + service_worker_registration_id != + controller.second->registration_id() + .service_worker_registration_id()) { + continue; + } + to_abort.push_back(controller.second.get()); + } + + for (auto* controller : to_abort) { + controller->Abort(BackgroundFetchFailureReason::SERVICE_WORKER_UNAVAILABLE, + base::DoNothing()); + } +} + +void BackgroundFetchScheduler::OnRegistrationQueried( + BackgroundFetchRegistration* registration) { + DCHECK(registration); + if (!active_controller_) + return; + + // The data manager only has the number of bytes from completed downloads, so + // augment this with the number of downloaded bytes from in-progress jobs. + if (active_controller_->registration_id().unique_id() == + registration->unique_id) { + registration->downloaded += + active_controller_->GetInProgressDownloadedBytes(); + } +} + +void BackgroundFetchScheduler::OnServiceWorkerDatabaseCorrupted( + int64_t service_worker_registration_id) { + AbortFetches(service_worker_registration_id); +} + +void BackgroundFetchScheduler::OnRegistrationDeleted(int64_t registration_id, + const GURL& pattern) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + AbortFetches(registration_id); +} + +void BackgroundFetchScheduler::OnStorageWiped() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + AbortFetches(blink::mojom::kInvalidServiceWorkerRegistrationId); } } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_scheduler.h b/content/browser/background_fetch/background_fetch_scheduler.h index 314f218..9bb3e75 100644 --- a/content/browser/background_fetch/background_fetch_scheduler.h +++ b/content/browser/background_fetch/background_fetch_scheduler.h
@@ -14,116 +14,137 @@ #include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" +#include "content/browser/background_fetch/background_fetch_event_dispatcher.h" #include "content/browser/background_fetch/background_fetch_registration_id.h" +#include "content/browser/service_worker/service_worker_context_core_observer.h" #include "content/common/content_export.h" #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h" namespace content { +class BackgroundFetchDataManager; +class BackgroundFetchDelegateProxy; +class BackgroundFetchJobController; class BackgroundFetchRegistrationId; +class BackgroundFetchRegistrationNotifier; class BackgroundFetchRequestInfo; // Maintains a list of Controllers and chooses which ones should launch new // downloads. -class CONTENT_EXPORT BackgroundFetchScheduler { +class CONTENT_EXPORT BackgroundFetchScheduler + : public BackgroundFetchDataManagerObserver, + public ServiceWorkerContextCoreObserver { public: - using FinishedCallback = - base::OnceCallback<void(const BackgroundFetchRegistrationId&, - blink::mojom::BackgroundFetchFailureReason)>; + BackgroundFetchScheduler( + BackgroundFetchDataManager* data_manager, + BackgroundFetchRegistrationNotifier* registration_notifier, + BackgroundFetchDelegateProxy* delegate_proxy, + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context); + ~BackgroundFetchScheduler() override; - // Interface for download job controllers. - class CONTENT_EXPORT Controller { - public: - using RequestFinishedCallback = - base::OnceCallback<void(scoped_refptr<BackgroundFetchRequestInfo>)>; + // Aborts the background fetch identified by |registration_id|. + // Must only be used for background fetches aborted by the developer, + // other cases are handled elsewhere. + void Abort(const BackgroundFetchRegistrationId& registration_id, + blink::mojom::BackgroundFetchFailureReason failure_reason, + blink::mojom::BackgroundFetchService::AbortCallback callback); - virtual ~Controller(); + // BackgroundFetchDataManagerObserver implementation. + void OnRegistrationCreated( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_requests, + bool start_paused) override; + void OnRegistrationLoadedAtStartup( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests) override; + void OnServiceWorkerDatabaseCorrupted( + int64_t service_worker_registration_id) override; + void OnRegistrationQueried( + BackgroundFetchRegistration* registration) override; - // Returns whether the Controller has any pending download requests. - virtual bool HasMoreRequests() = 0; - - // Requests the download manager to start fetching |request|. - virtual void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request, - RequestFinishedCallback callback) = 0; - - // Returns a list of requests that started in a previous session and did not - // complete. Clears the list of outstanding GUIDs in the controller. - virtual std::vector<scoped_refptr<BackgroundFetchRequestInfo>> - TakeOutstandingRequests() = 0; - - void Finish(blink::mojom::BackgroundFetchFailureReason reason_to_abort); - - const BackgroundFetchRegistrationId& registration_id() const { - return registration_id_; - } - - protected: - Controller(BackgroundFetchScheduler* scheduler, - const BackgroundFetchRegistrationId& registration_id, - FinishedCallback finished_callback); - - private: - // The |scheduler_| is guaranteed to outlive the controllers due to their - // declaration order in the BackgroundFetchContext. - BackgroundFetchScheduler* scheduler_; - - BackgroundFetchRegistrationId registration_id_; - FinishedCallback finished_callback_; - }; - - using MarkRequestCompleteCallback = - base::OnceCallback<void(blink::mojom::BackgroundFetchError)>; - using NextRequestCallback = - base::OnceCallback<void(blink::mojom::BackgroundFetchError, - scoped_refptr<BackgroundFetchRequestInfo>)>; - - class CONTENT_EXPORT RequestProvider { - public: - virtual ~RequestProvider() {} - - // Retrieves the next pending request for |registration_id| and invoke - // |callback| with it. - virtual void PopNextRequest( - const BackgroundFetchRegistrationId& registration_id, - NextRequestCallback callback) = 0; - - // Marks |request_info| as complete and calls |callback| when done. - virtual void MarkRequestAsComplete( - const BackgroundFetchRegistrationId& registration_id, - scoped_refptr<BackgroundFetchRequestInfo> request_info, - MarkRequestCompleteCallback callback) = 0; - }; - - explicit BackgroundFetchScheduler(RequestProvider* request_provider); - ~BackgroundFetchScheduler(); - - // Adds a new job controller to the scheduler. May immediately start to - // schedule jobs for |controller|. - void AddJobController(Controller* controller); - - // Removes the |controller| from the scheduler. Pending updates will be - // ignored and it won't be considered for further requests. - void RemoveJobController(Controller* controller); + // ServiceWorkerContextCoreObserver implementation. + void OnRegistrationDeleted(int64_t registration_id, + const GURL& pattern) override; + void OnStorageWiped() override; private: + friend class BackgroundFetchJobControllerTest; + friend class BackgroundFetchSchedulerTest; + void ScheduleDownload(); - void DidPopNextRequest( + // Helper method to abandon ongoing fetches for a given service worker. + // Abandons all of them if |service_worker_registration_id| is set to + // blink::mojom::kInvalidServiceWorkerRegistrationId. + void AbortFetches(int64_t service_worker_registration_id); + + std::unique_ptr<BackgroundFetchJobController> CreateInitializedController( + const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests, + bool start_paused); + + void FinishJob( + const BackgroundFetchRegistrationId& registration_id, + blink::mojom::BackgroundFetchFailureReason failure_reason, + base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback); + + void DidMarkForDeletion( + const BackgroundFetchRegistrationId& registration_id, + bool job_started, + base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback, blink::mojom::BackgroundFetchError error, - scoped_refptr<BackgroundFetchRequestInfo> request_info); + blink::mojom::BackgroundFetchFailureReason failure_reason); - void MarkRequestAsComplete( - scoped_refptr<BackgroundFetchRequestInfo> request_info); - void DidMarkRequestAsComplete(blink::mojom::BackgroundFetchError error); + void CleanupRegistration( + const BackgroundFetchRegistrationId& registration_id); - RequestProvider* request_provider_; + void DispatchClickEvent(const std::string& unique_id); - // The scheduler owns all the job controllers, holding them either in the - // controller queue or the guid to controller map. - base::circular_deque<Controller*> controller_queue_; - Controller* active_controller_ = nullptr; + // Owned by BackgroundFetchContext. + BackgroundFetchDataManager* data_manager_; + BackgroundFetchRegistrationNotifier* registration_notifier_; + BackgroundFetchDelegateProxy* delegate_proxy_; - base::WeakPtrFactory<BackgroundFetchScheduler> weak_ptr_factory_{this}; + BackgroundFetchEventDispatcher event_dispatcher_; + + // The order in which to process the job controllers. + base::circular_deque<std::string> controller_ids_; + + // Map from background fetch registration |unique_id|s to active job + // controllers. Must be destroyed before |data_manager_|, |scheduler_| and + // |registration_notifier_|. + std::map<std::string, std::unique_ptr<BackgroundFetchJobController>> + job_controllers_; + + // The current fetch jo controller that is being processed. + BackgroundFetchJobController* active_controller_ = nullptr; + + // Map from |unique_id|s to {|registration_id|, |registration|}. + // An entry in here means the fetch has completed. This information is needed + // after the fetch has completed to dispatch the backgroundfetchclick event. + // TODO(crbug.com/857122): Clean this up when the UI is no longer showing. + std::map<std::string, + std::pair<BackgroundFetchRegistrationId, + std::unique_ptr<BackgroundFetchRegistration>>> + completed_fetches_; + + base::WeakPtrFactory<BackgroundFetchScheduler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BackgroundFetchScheduler); };
diff --git a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc index ad18e4d..5df74e8 100644 --- a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc +++ b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -9,8 +9,11 @@ #include "base/guid.h" #include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" +#include "content/browser/background_fetch/background_fetch_job_controller.h" #include "content/browser/background_fetch/background_fetch_request_info.h" #include "content/browser/background_fetch/background_fetch_test_base.h" +#include "content/browser/background_fetch/background_fetch_test_data_manager.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" @@ -20,148 +23,148 @@ namespace content { -namespace { - -const int kExampleServiceWorkerRegistrationId = 1; -const char kExampleDeveloperId1[] = "my-example-id"; -const char kExampleDeveloperId2[] = "my-other-id"; - -class FakeController : public BackgroundFetchScheduler::Controller { +class FakeController : public BackgroundFetchJobController { public: - FakeController(const BackgroundFetchRegistrationId& registration_id, - BackgroundFetchScheduler* scheduler, - const std::string& name, + FakeController(BackgroundFetchDataManager* data_manager, + BackgroundFetchDelegateProxy* delegate_proxy, + const BackgroundFetchRegistrationId& registration_id, std::vector<std::string>* controller_sequence_list, - int total_jobs) - : BackgroundFetchScheduler::Controller(scheduler, - registration_id, - base::DoNothing()), - controller_sequence_list_(controller_sequence_list), - name_(name), - total_jobs_(total_jobs) {} - - ~FakeController() override {} - - // BackgroundFetchScheduler::Controller implementation: - bool HasMoreRequests() override { return jobs_started_ < total_jobs_; } - void StartRequest(scoped_refptr<BackgroundFetchRequestInfo> request, - RequestFinishedCallback callback) override { - DCHECK_LT(jobs_started_, total_jobs_); - ++jobs_started_; - controller_sequence_list_->push_back(name_ + - base::IntToString(jobs_started_)); - - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(std::move(callback), std::move(request))); + FinishedCallback finished_callback) + : BackgroundFetchJobController(data_manager, + delegate_proxy, + registration_id, + BackgroundFetchOptions(), + SkBitmap(), + 0ul, + base::DoNothing(), + std::move(finished_callback)), + controller_sequence_list_(controller_sequence_list) { + DCHECK(controller_sequence_list_); } - std::vector<scoped_refptr<BackgroundFetchRequestInfo>> - TakeOutstandingRequests() override { - return {}; + ~FakeController() override = default; + + void DidCompleteRequest( + const scoped_refptr<BackgroundFetchRequestInfo>& request) override { + // Record the completed request. Store everything after the origin and the + // slash, to be able to directly compare with the provided requests. + controller_sequence_list_->push_back( + request->fetch_request().url.path().substr(1)); + + // Continue normally. + BackgroundFetchJobController::DidCompleteRequest(request); } private: - int jobs_started_ = 0; std::vector<std::string>* controller_sequence_list_; - std::string name_; - int total_jobs_; }; -class BackgroundFetchSchedulerTest - : public BackgroundFetchTestBase, - public BackgroundFetchScheduler::RequestProvider { +class BackgroundFetchSchedulerTest : public BackgroundFetchTestBase { public: - BackgroundFetchSchedulerTest() : scheduler_(this) {} + BackgroundFetchSchedulerTest() = default; - // Posts itself as a task |number_of_barriers| times and on the last iteration - // invokes the quit_closure. - void PostQuitAfterRepeatingBarriers(base::Closure quit_closure, - int number_of_barriers) { - if (--number_of_barriers == 0) { - std::move(quit_closure).Run(); - return; - } + void SetUp() override { + BackgroundFetchTestBase::SetUp(); + data_manager_ = std::make_unique<BackgroundFetchTestDataManager>( + browser_context(), storage_partition(), + embedded_worker_test_helper()->context_wrapper()); + data_manager_->InitializeOnIOThread(); - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce( - &BackgroundFetchSchedulerTest::PostQuitAfterRepeatingBarriers, - base::Unretained(this), std::move(quit_closure), - number_of_barriers)); + delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>( + browser_context()->GetBackgroundFetchDelegate()); + + scheduler_ = std::make_unique<BackgroundFetchScheduler>( + data_manager_.get(), nullptr, delegate_proxy_.get(), + embedded_worker_test_helper()->context_wrapper()); } - void PopNextRequest( - const BackgroundFetchRegistrationId& registration_id, - BackgroundFetchScheduler::NextRequestCallback callback) override { - ServiceWorkerFetchRequest fetch_request(GURL(), "GET", - ServiceWorkerHeaderMap(), - Referrer(), false /* is_reload */); - auto request = base::MakeRefCounted<BackgroundFetchRequestInfo>( - 0 /* request_count */, fetch_request); - request->InitializeDownloadGuid(); - - std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE, - std::move(request)); - } - - void MarkRequestAsComplete( - const BackgroundFetchRegistrationId& registration_id, - scoped_refptr<BackgroundFetchRequestInfo> request_info, - BackgroundFetchScheduler::MarkRequestCompleteCallback closure) override { - std::move(closure).Run(blink::mojom::BackgroundFetchError::NONE); + void TearDown() override { + data_manager_ = nullptr; + delegate_proxy_ = nullptr; + scheduler_ = nullptr; + controller_sequence_list_.clear(); + BackgroundFetchTestBase::TearDown(); } protected: - BackgroundFetchScheduler scheduler_; + void InitializeControllerWithRequests( + const std::vector<std::string>& requests) { + std::vector<ServiceWorkerFetchRequest> fetch_requests; + for (auto& request : requests) { + ServiceWorkerFetchRequest fetch_request; + fetch_request.url = GURL(origin().GetURL().spec() + request); + CreateRequestWithProvidedResponse(fetch_request.method, fetch_request.url, + TestResponseBuilder(200).Build()); + fetch_requests.push_back(std::move(fetch_request)); + } + + int64_t sw_id = RegisterServiceWorker(); + BackgroundFetchRegistrationId registration_id( + sw_id, origin(), base::GenerateGUID(), base::GenerateGUID()); + data_manager_->CreateRegistration( + registration_id, fetch_requests, BackgroundFetchOptions(), SkBitmap(), + /* start_paused= */ false, base::DoNothing()); + thread_bundle_.RunUntilIdle(); + + auto controller = std::make_unique<FakeController>( + data_manager_.get(), delegate_proxy_.get(), registration_id, + &controller_sequence_list_, + base::BindOnce(&BackgroundFetchSchedulerTest::DidJobFinish, + base::Unretained(this))); + controller->InitializeRequestStatus(0 /* completed_downloads */, + requests.size(), + {} /* active_fetch_requests */, + /* start_paused= */ false); + scheduler_->job_controllers_[registration_id.unique_id()] = + std::move(controller); + scheduler_->controller_ids_.push_back(registration_id.unique_id()); + } + + void RunSchedulerToCompletion() { + scheduler_->ScheduleDownload(); + thread_bundle_.RunUntilIdle(); + } + + void DidJobFinish( + const BackgroundFetchRegistrationId& registration_id, + blink::mojom::BackgroundFetchFailureReason failure_reason, + base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback) { + DCHECK_EQ(failure_reason, blink::mojom::BackgroundFetchFailureReason::NONE); + scheduler_->job_controllers_.erase(registration_id.unique_id()); + scheduler_->active_controller_ = nullptr; + scheduler_->ScheduleDownload(); + } + + protected: std::vector<std::string> controller_sequence_list_; + + private: + std::unique_ptr<BackgroundFetchDelegateProxy> delegate_proxy_; + std::unique_ptr<BackgroundFetchTestDataManager> data_manager_; + std::unique_ptr<BackgroundFetchScheduler> scheduler_; }; -} // namespace - TEST_F(BackgroundFetchSchedulerTest, SingleController) { - BackgroundFetchRegistrationId registration_id1( - kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId1, - base::GenerateGUID()); - FakeController controller(registration_id1, &scheduler_, "A", - &controller_sequence_list_, 4); - - scheduler_.AddJobController(&controller); - - base::RunLoop().RunUntilIdle(); - - EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "A2", "A3", "A4")); + std::vector<std::string> requests = {"A1", "A2", "A3", "A4"}; + InitializeControllerWithRequests(requests); + RunSchedulerToCompletion(); + EXPECT_EQ(requests, controller_sequence_list_); } TEST_F(BackgroundFetchSchedulerTest, TwoControllers) { - BackgroundFetchRegistrationId registration_id1( - kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId1, - base::GenerateGUID()); - BackgroundFetchRegistrationId registration_id2( - kExampleServiceWorkerRegistrationId, origin(), kExampleDeveloperId2, - base::GenerateGUID()); - FakeController controller1(registration_id1, &scheduler_, "A", - &controller_sequence_list_, 4); - FakeController controller2(registration_id2, &scheduler_, "B", - &controller_sequence_list_, 4); + std::vector<std::string> all_requests = {"A1", "A2", "A3", "A4", + "B1", "B2", "B3"}; - scheduler_.AddJobController(&controller1); - scheduler_.AddJobController(&controller2); + // Create a controller with A1 -> A4. + InitializeControllerWithRequests( + std::vector<std::string>(all_requests.begin(), all_requests.begin() + 4)); - { - base::RunLoop run_loop; - PostQuitAfterRepeatingBarriers(run_loop.QuitClosure(), 3); - run_loop.Run(); + // Create a controller with B1 -> B4. + InitializeControllerWithRequests( + std::vector<std::string>(all_requests.begin() + 4, all_requests.end())); - // Only one task is run at a time so after 3 barrier iterations, 3 tasks - // should have been have run. - EXPECT_THAT(controller_sequence_list_, ElementsAre("A1", "A2", "A3")); - } - - base::RunLoop().RunUntilIdle(); - - EXPECT_THAT(controller_sequence_list_, - ElementsAre("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4")); + RunSchedulerToCompletion(); + EXPECT_EQ(all_requests, controller_sequence_list_); } } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc index f19f58f..2034b223 100644 --- a/content/browser/background_fetch/background_fetch_service_impl.cc +++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -121,8 +121,6 @@ std::move(callback).Run( blink::mojom::BackgroundFetchError::INVALID_ARGUMENT, base::nullopt /* registration */); - background_fetch::RecordRegistrationCreatedError( - blink::mojom::BackgroundFetchError::INVALID_ARGUMENT); return; }
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc index 508ce87..31cf681 100644 --- a/content/browser/background_fetch/background_fetch_service_unittest.cc +++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -12,10 +12,10 @@ #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" #include "build/build_config.h" #include "content/browser/background_fetch/background_fetch_context.h" +#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/background_fetch_embedded_worker_test_helper.h" #include "content/browser/background_fetch/background_fetch_job_controller.h" #include "content/browser/background_fetch/background_fetch_registration_id.h" @@ -29,6 +29,7 @@ #include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/bindings/message.h" #include "services/network/public/mojom/fetch_api.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom.h" #include "ui/gfx/geometry/size.h" @@ -36,6 +37,8 @@ namespace content { namespace { +using testing::_; + const char kExampleUniqueId[] = "7e57ab1e-c0de-a150-ca75-1e75f005ba11"; const char kExampleDeveloperId[] = "my-background-fetch"; const char kAlternativeDeveloperId[] = "my-alternative-fetch"; @@ -88,7 +91,9 @@ } // namespace -class BackgroundFetchServiceTest : public BackgroundFetchTestBase { +class BackgroundFetchServiceTest : public BackgroundFetchTestBase, + public BackgroundFetchDataManagerObserver, + public ServiceWorkerContextCoreObserver { public: BackgroundFetchServiceTest() = default; ~BackgroundFetchServiceTest() override = default; @@ -122,7 +127,6 @@ DCHECK(out_error); DCHECK(out_registration); - base::HistogramTester histogram_tester; base::RunLoop run_loop; std::vector<blink::mojom::FetchAPIRequestPtr> request_ptr; for (const auto& request : requests) { @@ -138,10 +142,6 @@ run_loop.Run(); - histogram_tester.ExpectBucketCount( - "BackgroundFetch.RegistrationCreatedError", - static_cast<int32_t>(*out_error), 1); - if (*out_error != blink::mojom::BackgroundFetchError::NONE) return BackgroundFetchRegistrationId(); @@ -182,8 +182,6 @@ DCHECK(out_error); DCHECK(out_registration); - base::AutoReset<bool> hang_registration_creation_for_testing( - &context_->hang_registration_creation_for_testing_, true); base::RunLoop run_loop; std::vector<blink::mojom::FetchAPIRequestPtr> request_ptr; for (const auto& request : requests) { @@ -242,7 +240,6 @@ blink::mojom::BackgroundFetchError* out_error) { DCHECK(out_error); - base::HistogramTester histogram_tester; base::RunLoop run_loop; service_->Abort(service_worker_registration_id, developer_id, unique_id, base::BindOnce(&BackgroundFetchServiceTest::DidGetError, @@ -250,20 +247,6 @@ run_loop.QuitClosure(), out_error)); run_loop.Run(); - - // Allow all the DatabaseTasks resulting from Abort to complete. - thread_bundle_.RunUntilIdle(); - - // We only delete the registration if we successfully abort. - if (*out_error == blink::mojom::BackgroundFetchError::NONE) { - // The error passed to the histogram counter is not related to this - // |*out_error|, but the result of - // BackgroundFetchDataManager::DeleteRegistration. For the purposes these - // tests, the deletion is always successful. - histogram_tester.ExpectBucketCount( - "BackgroundFetch.RegistrationDeletedError", - 0 /* blink::mojom::BackgroundFetchError::NONE */, 1); - } } // Synchronous wrapper for BackgroundFetchServiceImpl::GetRegistration(). @@ -301,13 +284,6 @@ run_loop.Run(); } - std::set<std::string> GetJobIDs() { - std::set<std::string> job_ids; - for (const auto& it : context_->job_controllers_) - job_ids.insert(it.first); - return job_ids; - } - // BackgroundFetchTestBase overrides: void SetUp() override { BackgroundFetchTestBase::SetUp(); @@ -320,6 +296,8 @@ std::make_unique<BackgroundFetchTestDataManager>( browser_context(), storage_partition(), embedded_worker_test_helper()->context_wrapper())); + context_->data_manager_->AddObserver(this); + embedded_worker_test_helper()->context_wrapper()->AddObserver(this); context_->InitializeOnIOThread(); service_ = std::make_unique<BackgroundFetchServiceImpl>( @@ -331,12 +309,41 @@ service_.reset(); + embedded_worker_test_helper()->context_wrapper()->RemoveObserver(this); + context_->data_manager_->RemoveObserver(this); context_ = nullptr; // Give pending shutdown operations a chance to finish. base::RunLoop().RunUntilIdle(); } + // BackgroundFetchDataManagerObserver implementation & mocks: + MOCK_METHOD6(OnRegistrationCreated, + void(const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_requests, + bool start_paused)); + MOCK_METHOD7(OnRegistrationLoadedAtStartup, + void(const BackgroundFetchRegistrationId& registration_id, + const BackgroundFetchRegistration& registration, + const BackgroundFetchOptions& options, + const SkBitmap& icon, + int num_completed_requests, + int num_requests, + std::vector<scoped_refptr<BackgroundFetchRequestInfo>> + active_fetch_requests)); + MOCK_METHOD1(OnRegistrationQueried, + void(BackgroundFetchRegistration* registration)); + MOCK_METHOD1(OnServiceWorkerDatabaseCorrupted, + void(int64_t service_worker_registration_id)); + + // ServiceWorkerContextCoreObserver implementation. + MOCK_METHOD2(OnRegistrationDeleted, + void(int64_t registration_id, const GURL& pattern)); + MOCK_METHOD0(OnStorageWiped, void()); + protected: ServiceWorkerFetchRequest CreateDefaultRequest() { return CreateRequestWithProvidedResponse( @@ -951,15 +958,6 @@ updated_second_registration_title, &error); EXPECT_EQ(blink::mojom::BackgroundFetchError::NONE, error); - // Calling UpdateUI for the aborted registration should fail (unlike, say, - // calling UpdateUI before resolving the waitUntil promise of a - // backgroundfetchsuccess or backgroundfetchfail event, both of which should - // work even though that registration is no longer active). - UpdateUI(aborted_registration_id.service_worker_registration_id(), - aborted_registration_id.developer_id(), - aborted_registration_id.unique_id(), "Bar", &error); - EXPECT_EQ(blink::mojom::BackgroundFetchError::INVALID_ID, error); - // Verify that the second registration's title was indeed updated, and that it // wasn't affected by the subsequent call to UpdateUI for the aborted // registration, by getting the second registration again. @@ -1115,8 +1113,7 @@ ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, service_worker_registration_id); - std::vector<ServiceWorkerFetchRequest> requests; - requests.emplace_back(); // empty, but valid + std::vector<ServiceWorkerFetchRequest> requests = {CreateDefaultRequest()}; BackgroundFetchOptions options; options.icons.push_back( @@ -1129,61 +1126,78 @@ blink::mojom::BackgroundFetchError error; BackgroundFetchRegistration registration; - FetchAndUnregisterServiceWorker(service_worker_registration_id, - kExampleDeveloperId, requests, options, - SkBitmap(), &error, ®istration); - ASSERT_EQ(error, - blink::mojom::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE); - EXPECT_TRUE(registration.developer_id.empty()); + { + using blink::mojom::BackgroundFetchError; + EXPECT_CALL(*this, + OnRegistrationDeleted(service_worker_registration_id, _)); + FetchAndUnregisterServiceWorker(service_worker_registration_id, + kExampleDeveloperId, requests, options, + SkBitmap(), &error, ®istration); + // There's a race condition between aborting due to unregistering the + // Service Worker, and a STORAGE_ERROR caused by the DatabaseTask as a + // result. + ASSERT_TRUE(error == BackgroundFetchError::STORAGE_ERROR || + error == BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE); + } } TEST_F(BackgroundFetchServiceTest, JobsInitializedOnBrowserRestart) { - // Initially there are no jobs in the JobController map. - EXPECT_TRUE(GetJobIDs().empty()); - int64_t service_worker_registration_id = RegisterServiceWorker(); ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, service_worker_registration_id); - std::vector<ServiceWorkerFetchRequest> requests; - requests.push_back(CreateRequestWithProvidedResponse( - "GET", GURL("https://example.com/mildly_funny_cat.txt"), - TestResponseBuilder(200) - .SetResponseData("A mildly funny cat.") - .AddResponseHeader("Content-Type", "text/plain") - .Build())); + std::vector<ServiceWorkerFetchRequest> requests = {CreateDefaultRequest()}; BackgroundFetchOptions options; + blink::mojom::BackgroundFetchError error; + BackgroundFetchRegistration registration; - // Only register the Fetch. In order to appropriately simulate a browser - // restart, we do not want the fetch to start yet. + // Start the fetch. The request is indefinitley pending so this will never + // finish. + BackgroundFetchRegistrationId registration_id; { - base::AutoReset<bool> hang_registration_creation_for_testing( - &context_->hang_registration_creation_for_testing_, true); - - StartFetch(service_worker_registration_id, kExampleDeveloperId, requests, - options, SkBitmap()); + EXPECT_CALL(*this, OnRegistrationCreated(_, _, _, _, _, _)); + registration_id = + Fetch(service_worker_registration_id, kExampleDeveloperId, requests, + options, SkBitmap(), &error, ®istration); + ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); } + // Check that the registration is in the DB. + { + std::vector<std::string> developer_ids; + GetDeveloperIds(service_worker_registration_id, &error, &developer_ids); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE); + ASSERT_EQ(developer_ids.size(), 1u); + EXPECT_EQ(developer_ids[0], kExampleDeveloperId); + } + + auto context = context_->service_worker_context_; // Simulate browser restart by re-creating |context_| and |service_|. + TearDown(); SetUp(); - // Queue up a GetRegistration DatabaseTask to run right after the - // initialization, but before the fetch is resumed. - BackgroundFetchRegistration registration; - blink::mojom::BackgroundFetchError error; - GetRegistration(service_worker_registration_id, kExampleDeveloperId, &error, - ®istration); - ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE); - EXPECT_EQ(registration.developer_id, kExampleDeveloperId); + // Overwrite pending request with a completable version. + CreateRequestWithProvidedResponse( + "GET", GURL("https://example.com/funny_cat.txt"), + TestResponseBuilder(200) + .SetResponseData("This request is no longer indefinitely pending.") + .Build()); - // Allow the fetch to completely finish. - thread_bundle_.RunUntilIdle(); + { + // The same BackgroundFetchRegistrationId is loaded. + EXPECT_CALL(*this, OnRegistrationLoadedAtStartup(registration_id, _, _, _, + _, _, _)); + // Allow restart process to go through. + thread_bundle_.RunUntilIdle(); + } - // At this point the fetch ran to completion. - EXPECT_TRUE(GetJobIDs().empty()); - GetRegistration(service_worker_registration_id, kExampleDeveloperId, &error, - ®istration); - EXPECT_EQ(error, blink::mojom::BackgroundFetchError::INVALID_ID); + // Check that the registration is not in the DB, which means it completed. + { + std::vector<std::string> developer_ids; + GetDeveloperIds(service_worker_registration_id, &error, &developer_ids); + EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE); + ASSERT_EQ(developer_ids.size(), 0u); + } } } // namespace content
diff --git a/content/browser/background_fetch/storage/mark_request_complete_task.cc b/content/browser/background_fetch/storage/mark_request_complete_task.cc index a51c412..4318236 100644 --- a/content/browser/background_fetch/storage/mark_request_complete_task.cc +++ b/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -8,7 +8,6 @@ #include "base/guid.h" #include "content/browser/background_fetch/background_fetch_cross_origin_filter.h" #include "content/browser/background_fetch/background_fetch_data_manager.h" -#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/background_fetch/storage/get_metadata_task.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" @@ -119,8 +118,6 @@ base::OnceClosure done_closure, bool is_available) { if (!is_available) { - for (auto& observer : data_manager()->observers()) - observer.OnQuotaExceeded(registration_id_); FinishWithError(blink::mojom::BackgroundFetchError::QUOTA_EXCEEDED); return; } @@ -306,11 +303,8 @@ void MarkRequestCompleteTask::FinishWithError( blink::mojom::BackgroundFetchError error) { - if (HasStorageError()) { + if (HasStorageError()) error = blink::mojom::BackgroundFetchError::STORAGE_ERROR; - for (auto& observer : data_manager()->observers()) - observer.OnFetchStorageError(registration_id_); - } ReportStorageError(); std::move(callback_).Run(error);
diff --git a/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/content/browser/background_fetch/storage/start_next_pending_request_task.cc index 469ce26..b265fc4 100644 --- a/content/browser/background_fetch/storage/start_next_pending_request_task.cc +++ b/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -5,8 +5,6 @@ #include "content/browser/background_fetch/storage/start_next_pending_request_task.h" #include "base/guid.h" -#include "content/browser/background_fetch/background_fetch_data_manager.h" -#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/common/service_worker/service_worker_utils.h" @@ -124,10 +122,6 @@ void StartNextPendingRequestTask::FinishWithError( blink::mojom::BackgroundFetchError error) { - if (HasStorageError()) { - for (auto& observer : data_manager()->observers()) - observer.OnFetchStorageError(registration_id_); - } ReportStorageError(); std::move(callback_).Run(error, std::move(next_request_));
diff --git a/content/browser/background_fetch/storage/update_registration_ui_task.cc b/content/browser/background_fetch/storage/update_registration_ui_task.cc deleted file mode 100644 index e86b2d2..0000000 --- a/content/browser/background_fetch/storage/update_registration_ui_task.cc +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/background_fetch/storage/update_registration_ui_task.h" - -#include "content/browser/background_fetch/background_fetch_data_manager.h" -#include "content/browser/background_fetch/background_fetch_data_manager_observer.h" -#include "content/browser/background_fetch/storage/database_helpers.h" -#include "content/browser/background_fetch/storage/image_helpers.h" -#include "content/browser/service_worker/service_worker_context_wrapper.h" -#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h" - -namespace content { - -namespace background_fetch { - -UpdateRegistrationUITask::UpdateRegistrationUITask( - DatabaseTaskHost* host, - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon, - UpdateRegistrationUICallback callback) - : DatabaseTask(host), - registration_id_(registration_id), - title_(title), - icon_(icon), - callback_(std::move(callback)), - weak_factory_(this) { - DCHECK(title_ || icon_); -} - -UpdateRegistrationUITask::~UpdateRegistrationUITask() = default; - -void UpdateRegistrationUITask::Start() { - if (title_ && icon_ && ShouldPersistIcon(*icon_)) { - // Directly overwrite whatever's stored in the SWDB. - SerializeIcon(*icon_, - base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon, - weak_factory_.GetWeakPtr())); - return; - } - - service_worker_context()->GetRegistrationUserData( - registration_id_.service_worker_registration_id(), - {UIOptionsKey(registration_id_.unique_id())}, - base::BindOnce(&UpdateRegistrationUITask::DidGetUIOptions, - weak_factory_.GetWeakPtr())); -} - -void UpdateRegistrationUITask::DidGetUIOptions( - const std::vector<std::string>& data, - blink::ServiceWorkerStatusCode status) { - switch (ToDatabaseStatus(status)) { - case DatabaseStatus::kFailed: - SetStorageErrorAndFinish( - BackgroundFetchStorageError::kServiceWorkerStorageError); - return; - case DatabaseStatus::kNotFound: - case DatabaseStatus::kOk: - break; - } - - if (data.empty() || !ui_options_.ParseFromString(data[0])) { - SetStorageErrorAndFinish( - BackgroundFetchStorageError::kServiceWorkerStorageError); - return; - } - - if (icon_ && ShouldPersistIcon(*icon_)) { - ui_options_.clear_icon(); - SerializeIcon(*icon_, - base::BindOnce(&UpdateRegistrationUITask::DidSerializeIcon, - weak_factory_.GetWeakPtr())); - } else { - StoreUIOptions(); - } -} - -void UpdateRegistrationUITask::DidSerializeIcon(std::string serialized_icon) { - ui_options_.set_icon(std::move(serialized_icon)); - StoreUIOptions(); -} - -void UpdateRegistrationUITask::StoreUIOptions() { - if (title_) - ui_options_.set_title(*title_); - - service_worker_context()->StoreRegistrationUserData( - registration_id_.service_worker_registration_id(), - registration_id_.origin().GetURL(), - {{UIOptionsKey(registration_id_.unique_id()), - ui_options_.SerializeAsString()}}, - base::BindOnce(&UpdateRegistrationUITask::DidUpdateUIOptions, - weak_factory_.GetWeakPtr())); -} - -void UpdateRegistrationUITask::DidUpdateUIOptions( - blink::ServiceWorkerStatusCode status) { - switch (ToDatabaseStatus(status)) { - case DatabaseStatus::kOk: - break; - case DatabaseStatus::kFailed: - case DatabaseStatus::kNotFound: - SetStorageErrorAndFinish( - BackgroundFetchStorageError::kServiceWorkerStorageError); - return; - } - - FinishWithError(blink::mojom::BackgroundFetchError::NONE); -} - -void UpdateRegistrationUITask::FinishWithError( - blink::mojom::BackgroundFetchError error) { - for (auto& observer : data_manager()->observers()) - observer.OnUpdatedUI(registration_id_, title_, icon_); - - ReportStorageError(); - - std::move(callback_).Run(error); - Finished(); // Destroys |this|. -} - -std::string UpdateRegistrationUITask::HistogramName() const { - return "UpdateRegistrationUITask"; -} - -} // namespace background_fetch - -} // namespace content
diff --git a/content/browser/background_fetch/storage/update_registration_ui_task.h b/content/browser/background_fetch/storage/update_registration_ui_task.h deleted file mode 100644 index 1958f7ce..0000000 --- a/content/browser/background_fetch/storage/update_registration_ui_task.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_UPDATE_REGISTRATION_UI_TASK_H_ -#define CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_UPDATE_REGISTRATION_UI_TASK_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/optional.h" -#include "content/browser/background_fetch/background_fetch.pb.h" -#include "content/browser/background_fetch/storage/database_task.h" -#include "third_party/blink/public/common/service_worker/service_worker_status_code.h" - -namespace content { - -namespace background_fetch { - -// Updates Background Fetch UI options. Accepts a new title. -class UpdateRegistrationUITask : public DatabaseTask { - public: - using UpdateRegistrationUICallback = - base::OnceCallback<void(blink::mojom::BackgroundFetchError)>; - - UpdateRegistrationUITask(DatabaseTaskHost* host, - const BackgroundFetchRegistrationId& registration_id, - const base::Optional<std::string>& title, - const base::Optional<SkBitmap>& icon, - UpdateRegistrationUICallback callback); - - ~UpdateRegistrationUITask() override; - - void Start() override; - - private: - void DidGetUIOptions(const std::vector<std::string>& data, - blink::ServiceWorkerStatusCode status); - - void DidSerializeIcon(std::string serialized_icon); - - void StoreUIOptions(); - - void DidUpdateUIOptions(blink::ServiceWorkerStatusCode status); - - void FinishWithError(blink::mojom::BackgroundFetchError error) override; - - std::string HistogramName() const override; - - BackgroundFetchRegistrationId registration_id_; - base::Optional<std::string> title_; - base::Optional<SkBitmap> icon_; - - proto::BackgroundFetchUIOptions ui_options_; - - UpdateRegistrationUICallback callback_; - - base::WeakPtrFactory<UpdateRegistrationUITask> - weak_factory_; // Keep as last. - - DISALLOW_COPY_AND_ASSIGN(UpdateRegistrationUITask); -}; - -} // namespace background_fetch - -} // namespace content - -#endif // CONTENT_BROWSER_BACKGROUND_FETCH_STORAGE_UPDATE_REGISTRATION_UI_TASK_H_
diff --git a/content/browser/background_sync/background_sync.proto b/content/browser/background_sync/background_sync.proto index 164c4c1..c65aed9 100644 --- a/content/browser/background_sync/background_sync.proto +++ b/content/browser/background_sync/background_sync.proto
@@ -19,7 +19,7 @@ required string tag = 2; // required SyncPeriodicity periodicity = 3; // required int64 min_period = 4; - required SyncNetworkState network_state = 5; + // required SyncNetworkState network_state = 5; // required SyncPowerState power_state = 6; required int32 num_attempts = 7; required int64 delay_until = 8;
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 4fa06d307..0ec1578 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -400,7 +400,6 @@ BackgroundSyncRegistrationOptions* options = registration->options(); options->tag = registration_proto.tag(); - options->network_state = registration_proto.network_state(); registration->set_num_attempts(registration_proto.num_attempts()); registration->set_delay_until( @@ -655,8 +654,6 @@ BackgroundSyncRegistrationProto* registration_proto = registrations_proto.add_registration(); registration_proto->set_tag(registration.options()->tag); - registration_proto->set_network_state( - registration.options()->network_state); registration_proto->set_num_attempts(registration.num_attempts()); registration_proto->set_delay_until( registration.delay_until().ToInternalValue()); @@ -837,7 +834,7 @@ bool BackgroundSyncManager::AreOptionConditionsMet( const BackgroundSyncRegistrationOptions& options) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return network_observer_->NetworkSufficient(options.network_state); + return network_observer_->NetworkSufficient(); } bool BackgroundSyncManager::IsRegistrationReadyToFire( @@ -1204,7 +1201,7 @@ scoped_refptr<ServiceWorkerVersion> active_version) { if (!active_version) return blink::ServiceWorkerStatusCode::kErrorFailed; - if (!network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE)) + if (!network_observer_->NetworkSufficient()) return blink::ServiceWorkerStatusCode::kErrorNetwork; int64_t registration_id = active_version->registration_id(); if (base::ContainsKey(emulated_offline_sw_, registration_id))
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index a163e68..d4662be 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -88,10 +88,7 @@ BackgroundSyncManagerTest() : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { sync_options_1_.tag = "foo"; - sync_options_1_.network_state = NETWORK_STATE_ONLINE; - sync_options_2_.tag = "bar"; - sync_options_2_.network_state = NETWORK_STATE_ONLINE; } void SetUp() override { @@ -744,23 +741,12 @@ EXPECT_FALSE(reg_1.Equals(reg_2)); } -TEST_F(BackgroundSyncManagerTest, RegistrationEqualsNetworkState) { - BackgroundSyncRegistration reg_1; - BackgroundSyncRegistration reg_2; - EXPECT_TRUE(reg_1.Equals(reg_2)); - reg_1.options()->network_state = NETWORK_STATE_ANY; - reg_2.options()->network_state = NETWORK_STATE_ONLINE; - EXPECT_FALSE(reg_1.Equals(reg_2)); -} - TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) { InitDelayedSyncEventTest(); BackgroundSyncRegistrationOptions options; // Set non-default values for each field. options.tag = "foo"; - EXPECT_NE(NETWORK_STATE_AVOID_CELLULAR, options.network_state); - options.network_state = NETWORK_STATE_AVOID_CELLULAR; // Store the registration. EXPECT_TRUE(Register(options));
diff --git a/content/browser/background_sync/background_sync_network_observer.cc b/content/browser/background_sync/background_sync_network_observer.cc index 496b401..15de5cc8 100644 --- a/content/browser/background_sync/background_sync_network_observer.cc +++ b/content/browser/background_sync/background_sync_network_observer.cc
@@ -67,26 +67,10 @@ OnConnectionChanged(connection_type); } -bool BackgroundSyncNetworkObserver::NetworkSufficient( - SyncNetworkState network_state) { +bool BackgroundSyncNetworkObserver::NetworkSufficient() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - switch (network_state) { - case NETWORK_STATE_ANY: - return true; - case NETWORK_STATE_AVOID_CELLULAR: - // Note that this returns true for CONNECTION_UNKNOWN to avoid never - // firing. - return connection_type_ != - network::mojom::ConnectionType::CONNECTION_NONE && - !network::NetworkConnectionTracker::IsConnectionCellular( - connection_type_); - case NETWORK_STATE_ONLINE: - return connection_type_ != - network::mojom::ConnectionType::CONNECTION_NONE; - } - - NOTREACHED(); + return connection_type_ != network::mojom::ConnectionType::CONNECTION_NONE; return false; }
diff --git a/content/browser/background_sync/background_sync_network_observer.h b/content/browser/background_sync/background_sync_network_observer.h index 8e587d0..8768cae 100644 --- a/content/browser/background_sync/background_sync_network_observer.h +++ b/content/browser/background_sync/background_sync_network_observer.h
@@ -28,9 +28,8 @@ // (For preventing flakes in tests) static void SetIgnoreNetworkChangesForTests(bool ignore); - // Returns true if the state of the network meets the needs of - // |network_state|. - bool NetworkSufficient(SyncNetworkState network_state); + // Returns true if the network is online. + bool NetworkSufficient(); // NetworkConnectionObserver overrides void OnConnectionChanged(
diff --git a/content/browser/background_sync/background_sync_network_observer_unittest.cc b/content/browser/background_sync/background_sync_network_observer_unittest.cc index 9ab8e09..95eafa1 100644 --- a/content/browser/background_sync/background_sync_network_observer_unittest.cc +++ b/content/browser/background_sync/background_sync_network_observer_unittest.cc
@@ -51,58 +51,18 @@ EXPECT_EQ(4, network_changed_count_); } -TEST_F(BackgroundSyncNetworkObserverTest, NetworkSufficientAnyNetwork) { - SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_3G); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ANY)); -} - -TEST_F(BackgroundSyncNetworkObserverTest, NetworkSufficientAvoidCellular) { - SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI); - EXPECT_TRUE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN); - EXPECT_TRUE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_2G); - EXPECT_FALSE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_3G); - EXPECT_FALSE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_4G); - EXPECT_FALSE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); - - SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE); - EXPECT_FALSE( - network_observer_->NetworkSufficient(NETWORK_STATE_AVOID_CELLULAR)); -} - TEST_F(BackgroundSyncNetworkObserverTest, ConditionsMetOnline) { SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE)); + EXPECT_TRUE(network_observer_->NetworkSufficient()); SetNetwork(network::mojom::ConnectionType::CONNECTION_3G); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE)); + EXPECT_TRUE(network_observer_->NetworkSufficient()); SetNetwork(network::mojom::ConnectionType::CONNECTION_UNKNOWN); - EXPECT_TRUE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE)); + EXPECT_TRUE(network_observer_->NetworkSufficient()); SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE); - EXPECT_FALSE(network_observer_->NetworkSufficient(NETWORK_STATE_ONLINE)); + EXPECT_FALSE(network_observer_->NetworkSufficient()); } TEST_F(BackgroundSyncNetworkObserverTest, GetNetworkOnConstruction) { @@ -120,7 +80,7 @@ // The network observer should have learned that the current network is not // the default (UNKNOWN) but is in fact NONE. EXPECT_EQ(1, network_changed_count_); - EXPECT_FALSE(observer->NetworkSufficient(NETWORK_STATE_ONLINE)); + EXPECT_FALSE(observer->NetworkSufficient()); } } // namespace content
diff --git a/content/browser/background_sync/background_sync_registration_options.cc b/content/browser/background_sync/background_sync_registration_options.cc index 7b8e1e7e..0fcfd08 100644 --- a/content/browser/background_sync/background_sync_registration_options.cc +++ b/content/browser/background_sync/background_sync_registration_options.cc
@@ -8,7 +8,7 @@ bool BackgroundSyncRegistrationOptions::Equals( const BackgroundSyncRegistrationOptions& other) const { - return tag == other.tag && network_state == other.network_state; + return tag == other.tag; } } // namespace content
diff --git a/content/browser/background_sync/background_sync_registration_options.h b/content/browser/background_sync/background_sync_registration_options.h index 5c81e308..dbbe27b5 100644 --- a/content/browser/background_sync/background_sync_registration_options.h +++ b/content/browser/background_sync/background_sync_registration_options.h
@@ -19,7 +19,6 @@ bool Equals(const BackgroundSyncRegistrationOptions& other) const; std::string tag; - SyncNetworkState network_state = NETWORK_STATE_ONLINE; }; } // namespace content
diff --git a/content/browser/background_sync/background_sync_service_impl.cc b/content/browser/background_sync/background_sync_service_impl.cc index 5ecef2f2..e4a13c56 100644 --- a/content/browser/background_sync/background_sync_service_impl.cc +++ b/content/browser/background_sync/background_sync_service_impl.cc
@@ -23,7 +23,6 @@ BackgroundSyncRegistrationOptions out; out.tag = in->tag; - out.network_state = static_cast<SyncNetworkState>(in->network_state); return out; } @@ -31,8 +30,6 @@ const BackgroundSyncRegistration& in) { blink::mojom::SyncRegistrationPtr out(blink::mojom::SyncRegistration::New()); out->tag = in.options()->tag; - out->network_state = static_cast<blink::mojom::BackgroundSyncNetworkState>( - in.options()->network_state); return out; } @@ -59,15 +56,6 @@ COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX, BACKGROUND_SYNC_STATUS_PERMISSION_DENIED); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ANY, - SyncNetworkState::NETWORK_STATE_ANY); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::AVOID_CELLULAR, - SyncNetworkState::NETWORK_STATE_AVOID_CELLULAR); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ONLINE, - SyncNetworkState::NETWORK_STATE_ONLINE); -COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::MAX, - SyncNetworkState::NETWORK_STATE_ONLINE); - BackgroundSyncServiceImpl::~BackgroundSyncServiceImpl() { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(background_sync_context_->background_sync_manager());
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index 20c7c4f..eae1ad7 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -1105,7 +1105,7 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginFieldTrialTest, Test) { bool expected_to_isolate = !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials); + switches::kDisableSiteIsolation); auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); EXPECT_EQ(expected_to_isolate, policy->IsIsolatedOrigin(url::Origin::Create( @@ -1134,7 +1134,7 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginCommandLineAndFieldTrialTest, Test) { auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); // --isolate-origins should take effect regardless of the - // kDisableSiteIsolationTrials opt-out flag. + // kDisableSiteIsolation opt-out flag. EXPECT_TRUE(policy->IsIsolatedOrigin( url::Origin::Create(GURL("https://cmd.line.com/")))); EXPECT_TRUE(policy->IsIsolatedOrigin( @@ -1143,7 +1143,7 @@ // Field trial origins should also take effect, but only if the opt-out flag // is not present. bool expected_to_isolate = !base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials); + switches::kDisableSiteIsolation); EXPECT_EQ(expected_to_isolate, policy->IsIsolatedOrigin(url::Origin::Create( GURL("https://field.trial.com/")))); EXPECT_EQ( @@ -1315,7 +1315,7 @@ EXPECT_TRUE(load_observer.last_navigation_succeeded()); } -// Ensure that --disable-site-isolation-trials disables field trials. +// Ensure that --disable-site-isolation-trials disables origin isolation. class IsolatedOriginTrialOverrideTest : public IsolatedOriginFieldTrialTest { public: IsolatedOriginTrialOverrideTest() {} @@ -1323,7 +1323,7 @@ ~IsolatedOriginTrialOverrideTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kDisableSiteIsolationTrials); + command_line->AppendSwitch(switches::kDisableSiteIsolation); } private: @@ -1349,7 +1349,7 @@ void SetUpCommandLine(base::CommandLine* command_line) override { IsolatedOriginTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kDisableSiteIsolationTrials); + command_line->AppendSwitch(switches::kDisableSiteIsolation); } private:
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index f8c5f414..60ed706 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -409,8 +409,8 @@ } #if defined(OS_CHROMEOS) -void NetworkServiceClient::OnUsedTrustAnchor(const std::string& username_hash) { - GetContentClient()->browser()->OnUsedTrustAnchor(username_hash); +void NetworkServiceClient::OnTrustAnchorUsed(const std::string& username_hash) { + GetContentClient()->browser()->OnTrustAnchorUsed(username_hash); } #endif
diff --git a/content/browser/network_service_client.h b/content/browser/network_service_client.h index 70cc35e..0f45d216 100644 --- a/content/browser/network_service_client.h +++ b/content/browser/network_service_client.h
@@ -55,7 +55,7 @@ bool fatal, OnSSLCertificateErrorCallback response) override; #if defined(OS_CHROMEOS) - void OnUsedTrustAnchor(const std::string& username_hash) override; + void OnTrustAnchorUsed(const std::string& username_hash) override; #endif void OnFileUploadRequested(uint32_t process_id, bool async,
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index f7d024b7..bc5fa1c1 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -39,6 +39,7 @@ child_allocated_local_surface_id, const base::Optional<base::TimeTicks>& child_local_surface_id_allocation_time) = 0; + virtual std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() = 0; }; // This class owns a DelegatedFrameHost, and will dynamically attach and @@ -63,10 +64,6 @@ // These will not return nullptr until Destroy is called. DelegatedFrameHost* GetDelegatedFrameHost(); - // Ensure that the currect compositor frame be cleared (even if it is - // potentially visible). - void ClearCompositorFrame(); - bool RequestRepaintForTesting(); // Return the parameters of the most recently received frame, or nullptr if @@ -138,7 +135,8 @@ void OnBeginFrame(base::TimeTicks frame_time) override; void OnFrameTokenChanged(uint32_t frame_token) override; float GetDeviceScaleFactor() const override; - void WasEvicted() override; + void AllocateNewSurfaceIdOnEviction() override; + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; base::WeakPtr<BrowserCompositorMac> GetWeakPtr() { return weak_factory_.GetWeakPtr();
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index 97b8894..432a1b61 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -83,15 +83,6 @@ return delegated_frame_host_.get(); } -void BrowserCompositorMac::ClearCompositorFrame() { - // Make sure that we no longer hold a compositor lock by un-suspending the - // compositor. This ensures that we are able to swap in a new blank frame to - // replace any old content. - // https://crbug.com/739621 - if (delegated_frame_host_) - delegated_frame_host_->ClearDelegatedFrame(); -} - bool BrowserCompositorMac::RequestRepaintForTesting() { dfh_local_surface_id_allocator_.GenerateId(); const viz::LocalSurfaceId& new_local_surface_id = @@ -249,15 +240,16 @@ (new_state != UseParentLayerCompositor || parent_ui_layer_ != root_layer_->parent())) { DCHECK(root_layer_->parent()); + state_ = HasNoCompositor; root_layer_->parent()->RemoveObserver(this); root_layer_->parent()->Remove(root_layer_.get()); delegated_frame_host_->WasHidden(); delegated_frame_host_->DetachFromCompositor(); - state_ = HasNoCompositor; } // Transition HasNoCompositor -> HasAttachedCompositor. if (state_ == HasNoCompositor && new_state == HasAttachedCompositor) { + state_ = HasAttachedCompositor; recyclable_compositor_ = ui::RecyclableCompositorMacFactory::Get()->CreateCompositor( content::GetContextFactory(), content::GetContextFactoryPrivate()); @@ -274,11 +266,11 @@ delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_, false /* record_presentation_time */); recyclable_compositor_->Unsuspend(); - state_ = HasAttachedCompositor; } // Transition HasAttachedCompositor -> HasNoCompositor. if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) { + state_ = HasNoCompositor; // Marking the DelegatedFrameHost as removed from the window hierarchy is // necessary to remove all connections to its old ui::Compositor. delegated_frame_host_->WasHidden(); @@ -288,7 +280,6 @@ recyclable_compositor_->InvalidateSurface(); ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor( std::move(recyclable_compositor_)); - state_ = HasNoCompositor; } // Transition HasNoCompositor -> UseParentLayerCompositor. @@ -296,13 +287,13 @@ DCHECK(parent_ui_layer_); DCHECK(parent_ui_layer_->GetCompositor()); DCHECK(!root_layer_->parent()); + state_ = UseParentLayerCompositor; delegated_frame_host_->AttachToCompositor( parent_ui_layer_->GetCompositor()); delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_, false /* record_presentation_time */); parent_ui_layer_->Add(root_layer_.get()); parent_ui_layer_->AddObserver(this); - state_ = UseParentLayerCompositor; } } @@ -361,10 +352,15 @@ return dfh_display_.device_scale_factor(); } -void BrowserCompositorMac::WasEvicted() { +void BrowserCompositorMac::AllocateNewSurfaceIdOnEviction() { dfh_local_surface_id_allocator_.GenerateId(); } +std::vector<viz::SurfaceId> +BrowserCompositorMac::CollectSurfaceIdsForEviction() { + return client_->CollectSurfaceIdsForEviction(); +} + void BrowserCompositorMac::DidNavigate() { // The first navigation does not need a new LocalSurfaceID. The renderer can // use the ID that was already provided.
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 8bb353b..8eb19b1 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -271,14 +271,6 @@ std::move(hit_test_region_list)); } -void DelegatedFrameHost::ClearDelegatedFrame() { - // Ensure that we are able to swap in a new blank frame to replace any old - // content. This will result in a white flash if we switch back to this - // content. - // https://crbug.com/739621 - EvictDelegatedFrame(); -} - void DelegatedFrameHost::DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) { renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources); @@ -344,12 +336,19 @@ if (!HasSavedFrame()) return; + DCHECK(!client_->DelegatedFrameHostIsVisible()); std::vector<viz::SurfaceId> surface_ids = { - viz::SurfaceId(frame_sink_id_, local_surface_id_)}; - DCHECK(host_frame_sink_manager_); - host_frame_sink_manager_->EvictSurfaces(surface_ids); + client_->CollectSurfaceIdsForEviction()}; + // This list could be empty if this frame is not in the frame tree (can happen + // during navigation, construction, destruction, or in unit tests). + if (!surface_ids.empty()) { + DCHECK(std::find(surface_ids.begin(), surface_ids.end(), + GetCurrentSurfaceId()) != surface_ids.end()); + DCHECK(host_frame_sink_manager_); + host_frame_sink_manager_->EvictSurfaces(surface_ids); + } frame_evictor_->OnSurfaceDiscarded(); - client_->WasEvicted(); + client_->AllocateNewSurfaceIdOnEviction(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index 424262e..95fb1451 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -50,7 +50,8 @@ virtual void OnBeginFrame(base::TimeTicks frame_time) = 0; virtual void OnFrameTokenChanged(uint32_t frame_token) = 0; virtual float GetDeviceScaleFactor() const = 0; - virtual void WasEvicted() = 0; + virtual void AllocateNewSurfaceIdOnEviction() = 0; + virtual std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() = 0; }; // The DelegatedFrameHost is used to host all of the RenderWidgetHostView state @@ -85,9 +86,6 @@ void OnLostSharedContext() override; void OnLostVizProcess() override; - // FrameEvictorClient implementation. - void EvictDelegatedFrame() override; - void ResetFallbackToFirstNavigationSurface(); // viz::mojom::CompositorFrameSinkClient implementation. @@ -113,7 +111,6 @@ const viz::LocalSurfaceId& local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList> hit_test_region_list); - void ClearDelegatedFrame(); void WasHidden(); // TODO(ccameron): Include device scale factor here. void WasShown(const viz::LocalSurfaceId& local_surface_id, @@ -186,6 +183,9 @@ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking); + // FrameEvictorClient implementation. + void EvictDelegatedFrame() override; + SkColor GetGutterColor() const; void CreateCompositorFrameSinkSupport();
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/content/browser/renderer_host/delegated_frame_host_client_aura.cc index 62bfbbf..973a35f 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.cc +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -55,8 +55,13 @@ return render_widget_host_view_->device_scale_factor_; } -void DelegatedFrameHostClientAura::WasEvicted() { - render_widget_host_view_->WasEvicted(); +void DelegatedFrameHostClientAura::AllocateNewSurfaceIdOnEviction() { + render_widget_host_view_->AllocateNewSurfaceIdOnEviction(); +} + +std::vector<viz::SurfaceId> +DelegatedFrameHostClientAura::CollectSurfaceIdsForEviction() { + return render_widget_host_view_->host()->CollectSurfaceIdsForEviction(); } } // namespace content
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.h b/content/browser/renderer_host/delegated_frame_host_client_aura.h index 9193162d..8f93648 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.h +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -33,7 +33,8 @@ void OnBeginFrame(base::TimeTicks frame_time) override; void OnFrameTokenChanged(uint32_t frame_token) override; float GetDeviceScaleFactor() const override; - void WasEvicted() override; + void AllocateNewSurfaceIdOnEviction() override; + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; private: RenderWidgetHostViewAura* render_widget_host_view_;
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc index 11e745c..e4d32f5b 100644 --- a/content/browser/renderer_host/frame_connector_delegate.cc +++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -50,6 +50,7 @@ render_widget_host->SetAutoResize(resize_params.auto_resize_enabled, resize_params.min_size_for_auto_resize, resize_params.max_size_for_auto_resize); + render_widget_host->SetPageScaleFactor(resize_params.page_scale_factor); render_widget_host->SynchronizeVisualProperties(); }
diff --git a/content/browser/renderer_host/input/fling_scheduler.cc b/content/browser/renderer_host/input/fling_scheduler.cc index b61fc65..65153443 100644 --- a/content/browser/renderer_host/input/fling_scheduler.cc +++ b/content/browser/renderer_host/input/fling_scheduler.cc
@@ -36,7 +36,10 @@ base::WeakPtr<FlingController> fling_controller) { DCHECK(fling_controller); fling_controller_ = fling_controller; - DCHECK(!observed_compositor_); + // Convert the following if-statement back to DCHECK(!observed_compositor_) + // once https://crbug.com/897216 is fixed. + if (observed_compositor_) + return; ui::Compositor* compositor = GetCompositor(); // If a ui::Compositor can't be obtained, ask the host for BeginFrames.
diff --git a/content/browser/renderer_host/input/touch_emulator.cc b/content/browser/renderer_host/input/touch_emulator.cc index e5cfa600..ab7c6f7 100644 --- a/content/browser/renderer_host/input/touch_emulator.cc +++ b/content/browser/renderer_host/input/touch_emulator.cc
@@ -71,6 +71,7 @@ ui::GestureProviderConfigType::CURRENT_PLATFORM), double_tap_enabled_(true), use_2x_cursors_(false), + pinch_gesture_mode_for_testing_(false), emulated_stream_active_sequence_count_(0), native_stream_active_sequence_count_(0), last_emulated_start_target_(nullptr), @@ -516,6 +517,7 @@ WebGestureEvent scroll_event( WebInputEvent::kGestureScrollEnd, ModifiersWithoutMouseButtons(event), event.TimeStamp(), blink::kWebGestureDeviceTouchscreen); + scroll_event.unique_touch_event_id = event.unique_touch_event_id; client_->ForwardEmulatedGestureEvent(scroll_event); } @@ -571,7 +573,11 @@ } bool TouchEmulator::InPinchGestureMode() const { - return shift_pressed_; + return shift_pressed_ || pinch_gesture_mode_for_testing_; +} + +void TouchEmulator::SetPinchGestureModeForTesting(bool pinch_gesture_mode) { + pinch_gesture_mode_for_testing_ = pinch_gesture_mode; } } // namespace content
diff --git a/content/browser/renderer_host/input/touch_emulator.h b/content/browser/renderer_host/input/touch_emulator.h index 55fabad..20d2656e 100644 --- a/content/browser/renderer_host/input/touch_emulator.h +++ b/content/browser/renderer_host/input/touch_emulator.h
@@ -85,6 +85,14 @@ // Cancel any touches, for example, when focus is lost. void CancelTouch(); + // This is needed because SyntheticGestureSmoothDrag doesn't support setting + // key-modifiers on the drag sequence. + // https://crbug.com/901374. + void SetPinchGestureModeForTesting(bool pinch_gesture_mode); + bool suppress_next_fling_cancel_for_testing() const { + return suppress_next_fling_cancel_; + } + private: // ui::GestureProviderClient implementation. void OnGestureEvent(const ui::GestureEventData& gesture) override; @@ -147,6 +155,7 @@ bool mouse_pressed_; bool shift_pressed_; + bool pinch_gesture_mode_for_testing_; blink::WebTouchEvent touch_event_; int emulated_stream_active_sequence_count_;
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 31919ead..4bd470be 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -997,4 +997,28 @@ ClosePageIgnoringUnloadEvents(); } +std::vector<viz::SurfaceId> RenderViewHostImpl::CollectSurfaceIdsForEviction() { + if (!is_active()) + return {}; + RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); + if (!rfh || !rfh->IsCurrent()) + return {}; + FrameTreeNode* root = rfh->frame_tree_node(); + FrameTree* tree = root->frame_tree(); + std::vector<viz::SurfaceId> ids; + for (FrameTreeNode* node : tree->SubtreeNodes(root)) { + if (!node->current_frame_host()->is_local_root()) + continue; + RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( + node->current_frame_host()->GetView()); + if (!view) + continue; + viz::SurfaceId id = view->GetCurrentSurfaceId(); + if (id.is_valid()) + ids.push_back(id); + view->set_is_evicted(); + } + return ids; +} + } // namespace content
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index 5e76c0fe..b330857 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -216,6 +216,10 @@ // and RenderFrameProxyHosts currently using it. int ref_count() { return frames_ref_count_; } + // Called during frame eviction to return all SurfaceIds in the frame tree. + // Marks all views in the frame tree as evicted. + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction(); + // NOTE: Do not add functions that just send an IPC message that are called in // one or two places. Have the caller send the IPC message directly (unless // the caller places are in different platforms, in which case it's better
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc index b804108..f7bb0bc 100644 --- a/content/browser/renderer_host/render_widget_host_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -5,8 +5,10 @@ #include <vector> #include "base/run_loop.h" +#include "base/test/bind_test_util.h" #include "base/time/time.h" #include "content/browser/renderer_host/input/input_router_impl.h" +#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h" #include "content/browser/renderer_host/input/touch_action_filter.h" #include "content/browser/renderer_host/input/touch_emulator.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -141,6 +143,58 @@ base::TimeDelta simulated_event_time_delta_; }; +// Synthetic mouse events not allowed on Android. +#if !defined(OS_ANDROID) +// This test makes sure that TouchEmulator doesn't emit a GestureScrollEnd without a valid +// unique_touch_event_id when it sees a GestureFlingStart terminating the underlying mouse +// scroll sequence. If the GestureScrollEnd is given a unique_touch_event_id of 0, then a +// crash will occur. +IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest, + TouchEmulatorPinchWithGestureFling) { + auto* touch_emulator = host()->GetTouchEmulator(); + touch_emulator->Enable(TouchEmulator::Mode::kEmulatingTouchFromMouse, + ui::GestureProviderConfigType::GENERIC_MOBILE); + touch_emulator->SetPinchGestureModeForTesting(true); + + TestInputEventObserver observer; + host()->AddInputEventObserver(&observer); + + SyntheticSmoothDragGestureParams params; + params.start_point = gfx::PointF(10.f, 110.f); + params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; + params.distances.push_back(gfx::Vector2d(0, -10)); + params.distances.push_back(gfx::Vector2d(0, -10)); + params.distances.push_back(gfx::Vector2d(0, -10)); + params.distances.push_back(gfx::Vector2d(0, -10)); + params.speed_in_pixels_s = 1200; + + std::unique_ptr<SyntheticSmoothDragGesture> gesture( + new SyntheticSmoothDragGesture(params)); + + InputEventAckWaiter scroll_end_ack_waiter( + host(), blink::WebInputEvent::kGestureScrollEnd); + base::RunLoop run_loop; + host()->QueueSyntheticGesture( + std::move(gesture), + base::BindOnce( + base::BindLambdaForTesting([&](SyntheticGesture::Result result) { + EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result); + run_loop.Quit(); + }))); + run_loop.Run(); + scroll_end_ack_waiter.Wait(); + + // Verify that a GestureFlingStart was suppressed by the TouchEmulator, and + // that we generated a GestureScrollEnd and routed it without crashing. + TestInputEventObserver::EventTypeVector dispatched_events = + observer.GetAndResetDispatchedEventTypes(); + auto it_gse = std::find(dispatched_events.begin(), dispatched_events.end(), + blink::WebInputEvent::kGestureScrollEnd); + EXPECT_NE(dispatched_events.end(), it_gse); + EXPECT_TRUE(touch_emulator->suppress_next_fling_cancel_for_testing()); +} +#endif // !defined(OS_ANDROID) + IN_PROC_BROWSER_TEST_F(RenderWidgetHostTouchEmulatorBrowserTest, TouchEmulator) { // All touches will be immediately acked instead of sending them to the
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index ab1afd5..b641797 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -408,6 +408,7 @@ is_hidden_(hidden), visual_properties_ack_pending_(false), auto_resize_enabled_(false), + page_scale_factor_(1.f), waiting_for_screen_rects_ack_(false), is_unresponsive_(false), in_flight_event_count_(0), @@ -793,9 +794,11 @@ SendScreenRects(); RestartInputEventAckTimeoutIfNecessary(); - Send(new WidgetMsg_WasShown(routing_id_, record_presentation_time - ? base::TimeTicks::Now() - : base::TimeTicks())); + Send(new WidgetMsg_WasShown( + routing_id_, + record_presentation_time ? base::TimeTicks::Now() : base::TimeTicks(), + view_->is_evicted())); + view_->reset_is_evicted(); process_->UpdateClientPriority(this); @@ -858,6 +861,8 @@ visual_properties->min_size_for_auto_resize = min_size_for_auto_resize_; visual_properties->max_size_for_auto_resize = max_size_for_auto_resize_; + visual_properties->page_scale_factor = page_scale_factor_; + if (view_) { visual_properties->new_size = view_->GetRequestedRendererSize(); visual_properties->capture_sequence_number = @@ -946,7 +951,9 @@ old_visual_properties_->visible_viewport_size != visual_properties->visible_viewport_size || old_visual_properties_->capture_sequence_number != - visual_properties->capture_sequence_number; + visual_properties->capture_sequence_number || + old_visual_properties_->page_scale_factor != + visual_properties->page_scale_factor; // We should throttle sending updated VisualProperties to the renderer to // the rate of commit. This ensures we don't overwhelm the renderer with @@ -2053,6 +2060,10 @@ max_size_for_auto_resize_ = max_size; } +void RenderWidgetHostImpl::SetPageScaleFactor(float page_scale_factor) { + page_scale_factor_ = page_scale_factor; +} + void RenderWidgetHostImpl::Destroy(bool also_delete) { DCHECK(!destroyed_); destroyed_ = true; @@ -3127,4 +3138,13 @@ DidUpdateVisualProperties(metadata); } +std::vector<viz::SurfaceId> +RenderWidgetHostImpl::CollectSurfaceIdsForEviction() { + RenderViewHostImpl* rvh = RenderViewHostImpl::From(this); + // A corresponding RenderViewHostImpl may not exist in unit tests. + if (!rvh) + return {}; + return rvh->CollectSurfaceIdsForEviction(); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index e180790..6eb985d 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -546,6 +546,9 @@ const gfx::Size& min_size, const gfx::Size& max_size); + // Allows the main frame's page scale factor to be tracked. + void SetPageScaleFactor(float page_scale_factor); + // Fills in the |visual_properties| struct. // Returns |false| if the update is redundant, |true| otherwise. bool GetVisualProperties(VisualProperties* visual_properties, @@ -711,6 +714,10 @@ // NotifyRendererResponsive. void RendererIsResponsive(); + // Called during frame eviction to return all SurfaceIds in the frame tree. + // Marks all views in the frame tree as evicted. + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction(); + protected: // --------------------------------------------------------------------------- // The following method is overridden by RenderViewHost to send upwards to @@ -977,6 +984,9 @@ // The maximum size for the render widget if auto-resize is enabled. gfx::Size max_size_for_auto_resize_; + // The page-scale factor of the main-frame. + float page_scale_factor_; + bool waiting_for_screen_rects_ack_; gfx::Rect last_view_screen_rect_; gfx::Rect last_window_screen_rect_;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index 09cec86..046451d 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -1361,7 +1361,9 @@ // are not associated with touch events, because non-synthetic events can be // created by ContentView. These will use the target found by the // RenderWidgetTargeter. These gesture events should always have a - // unique_touch_event_id of 0. + // unique_touch_event_id of 0. They must have a non-null target in order + // to get the coordinate transform. + DCHECK(target); touchscreen_gesture_target_.target = target; touchscreen_gesture_target_in_map_ = IsViewInMap(target); if (!root_view->GetTransformToViewCoordSpace(
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 65c16ecd..4a4f702 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -902,8 +902,9 @@ } void RenderWidgetHostViewAura::ClearCompositorFrame() { - if (delegated_frame_host_) - delegated_frame_host_->ClearDelegatedFrame(); + // This method is only used for content rendering timeout when surface sync is + // off. However, surface sync is always on on Aura platforms. + NOTREACHED(); } void RenderWidgetHostViewAura::ResetFallbackToFirstNavigationSurface() { @@ -2583,7 +2584,7 @@ host()->GetContentRenderingTimeoutFrom(view_aura->host()); } -void RenderWidgetHostViewAura::WasEvicted() { +void RenderWidgetHostViewAura::AllocateNewSurfaceIdOnEviction() { window_->UpdateLocalSurfaceIdFromEmbeddedClient(base::nullopt, base::nullopt); }
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 0c603555..902eb2e4 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -557,7 +557,7 @@ // Called when the window title is changed. void WindowTitleChanged(); - void WasEvicted(); + void AllocateNewSurfaceIdOnEviction(); const bool is_mus_browser_plugin_guest_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index d46f947..c20865a 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -3450,7 +3450,10 @@ // Make sure |parent_view_| is evicted to avoid interfering with the code // below. - parent_view_->delegated_frame_host_->EvictDelegatedFrame(); + parent_view_->Hide(); + static_cast<viz::FrameEvictorClient*>( + parent_view_->delegated_frame_host_.get()) + ->EvictDelegatedFrame(); size_t max_renderer_frames = FrameEvictionManager::GetInstance()->GetMaxNumberOfSavedFrames(); @@ -3560,7 +3563,10 @@ // Make sure |parent_view_| is evicted to avoid interfering with the code // below. - parent_view_->delegated_frame_host_->EvictDelegatedFrame(); + parent_view_->Hide(); + static_cast<viz::FrameEvictorClient*>( + parent_view_->delegated_frame_host_.get()) + ->EvictDelegatedFrame(); // The test logic below relies on having max_renderer_frames > 2. By default, // this value is calculated from total physical memory and causes the test to @@ -5789,7 +5795,8 @@ view_->Show(); viz::LocalSurfaceId id1 = view_->GetLocalSurfaceId(); view_->Hide(); - view_->ClearCompositorFrame(); + static_cast<viz::FrameEvictorClient*>(view_->delegated_frame_host_.get()) + ->EvictDelegatedFrame(); view_->Show(); viz::LocalSurfaceId id2 = view_->GetLocalSurfaceId(); EXPECT_NE(id1, id2);
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 0dd9895..9899b7b7 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -409,7 +409,7 @@ // this view or the target view has no current FrameSinkId. The latter may // happen if either view is not currently visible in the viewport. // This function is useful if there are multiple points to transform between - // the same two views. + // the same two views. |target_view| must be non-null. bool GetTransformToViewCoordSpace(RenderWidgetHostViewBase* target_view, gfx::Transform* transform); @@ -602,6 +602,10 @@ // Called when the RenderWidgetHostImpl has be initialized. virtual void OnRenderWidgetInit() {} + void set_is_evicted() { is_evicted_ = true; } + void reset_is_evicted() { is_evicted_ = false; } + bool is_evicted() { return is_evicted_; } + protected: explicit RenderWidgetHostViewBase(RenderWidgetHost* host); @@ -734,6 +738,8 @@ base::Optional<blink::WebGestureEvent> pending_touchpad_pinch_begin_; + bool is_evicted_ = false; + base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 09b8c3e..079101d 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -73,6 +73,8 @@ frame_connector_(nullptr), enable_viz_( base::FeatureList::IsEnabled(features::kVizDisplayCompositor)), + enable_surface_synchronization_( + features::IsSurfaceSynchronizationEnabled()), weak_factory_(this) { if (features::IsMultiProcessMash()) { // In Mus the RenderFrameProxy will eventually assign a viz::FrameSinkId @@ -755,7 +757,9 @@ } viz::SurfaceId RenderWidgetHostViewChildFrame::GetCurrentSurfaceId() const { - return last_activated_surface_info_.id(); + return enable_surface_synchronization_ + ? viz::SurfaceId(frame_sink_id_, GetLocalSurfaceId()) + : last_activated_surface_info_.id(); } bool RenderWidgetHostViewChildFrame::HasSize() const {
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h index 38de575..dc5ee6e 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.h +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -316,6 +316,7 @@ viz::FrameSinkId parent_frame_sink_id_; const bool enable_viz_; + const bool enable_surface_synchronization_; bool has_frame_ = false; viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 32ea5ffa0..ac092bd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -397,6 +397,7 @@ child_allocated_local_surface_id, const base::Optional<base::TimeTicks>& child_local_surface_id_allocation_time) override; + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; // AcceleratedWidgetMacNSView implementation. void AcceleratedWidgetCALayerParamsUpdated() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index b1461077..5ec32dd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -118,6 +118,11 @@ return host()->SynchronizeVisualProperties(); } +std::vector<viz::SurfaceId> +RenderWidgetHostViewMac::CollectSurfaceIdsForEviction() { + return host()->CollectSurfaceIdsForEviction(); +} + //////////////////////////////////////////////////////////////////////////////// // AcceleratedWidgetMacNSView, public: @@ -1070,7 +1075,9 @@ } void RenderWidgetHostViewMac::ClearCompositorFrame() { - browser_compositor_->ClearCompositorFrame(); + // This method is only used for content rendering timeout when surface sync is + // off. However, surface sync is always on on Mac. + NOTREACHED(); } void RenderWidgetHostViewMac::ResetFallbackToFirstNavigationSurface() { @@ -1287,6 +1294,10 @@ } viz::SurfaceId RenderWidgetHostViewMac::GetCurrentSurfaceId() const { + // |browser_compositor_| could be null if this method is called during its + // destruction. + if (!browser_compositor_) + return viz::SurfaceId(); return browser_compositor_->GetDelegatedFrameHost()->GetCurrentSurfaceId(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index ce9fed4..0b9cb4f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -2202,16 +2202,6 @@ } } -TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) { - BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor(); - ui::Compositor* ui_compositor = browser_compositor->GetCompositor(); - EXPECT_NE(ui_compositor, nullptr); - EXPECT_FALSE(ui_compositor->IsLocked()); - rwhv_mac_->ClearCompositorFrame(); - EXPECT_EQ(browser_compositor->GetCompositor(), ui_compositor); - EXPECT_FALSE(ui_compositor->IsLocked()); -} - // This test verifies that in AutoResize mode a child-allocated // viz::LocalSurfaceId will be properly routed and stored in the parent. TEST_F(RenderWidgetHostViewMacTest, ChildAllocationAcceptedInParent) {
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 369f108c8..44dc9764 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -133,6 +133,7 @@ #endif #if defined(OS_MACOSX) +#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h" #include "ui/base/test/scoped_preferred_scroller_style_mac.h" #endif @@ -10706,6 +10707,86 @@ } #endif // defined(OS_ANDROID) +// This test verifies that the main-frame's page scale factor propagates to +// the compositor layertrees in each of the child processes. +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, + PageScaleFactorPropagatesToOOPIFs) { + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b(c),d)")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + ASSERT_EQ(2u, root->child_count()); + FrameTreeNode* child_b = root->child_at(0); + FrameTreeNode* child_c = root->child_at(1); + ASSERT_EQ(1U, child_b->child_count()); + FrameTreeNode* child_d = child_b->child_at(0); + + ASSERT_TRUE(child_b); + ASSERT_TRUE(child_c); + ASSERT_TRUE(child_d); + + EXPECT_EQ( + " Site A ------------ proxies for B C D\n" + " |--Site B ------- proxies for A C D\n" + " | +--Site C -- proxies for A B D\n" + " +--Site D ------- proxies for A B C\n" + "Where A = http://a.com/\n" + " B = http://b.com/\n" + " C = http://c.com/\n" + " D = http://d.com/", + DepictFrameTree(root)); + + RenderFrameSubmissionObserver observer_a(root); + RenderFrameSubmissionObserver observer_b(child_b); + RenderFrameSubmissionObserver observer_c(child_c); + RenderFrameSubmissionObserver observer_d(child_d); + + // We need to observe a root frame submission to pick up the initial page + // scale factor. + observer_a.WaitForAnyFrameSubmission(); + + const float kPageScaleDelta = 2.f; + // On desktop systems we expect |current_page_scale| to be 1.f, but on + // Android it will typically be less than 1.f, and may take on arbitrary + // values. + float current_page_scale = + observer_a.LastRenderFrameMetadata().page_scale_factor; + float target_page_scale = current_page_scale * kPageScaleDelta; + + SyntheticPinchGestureParams params; + auto* host = static_cast<RenderWidgetHostImpl*>( + root->current_frame_host()->GetRenderWidgetHost()); + gfx::Rect bounds(host->GetView()->GetViewBounds().size()); + // The synthetic gesture code expects a location in root-view coordinates. + params.anchor = gfx::PointF(bounds.CenterPoint()); + // In SyntheticPinchGestureParams, |scale_factor| is really a delta. + params.scale_factor = kPageScaleDelta; +#if defined(OS_MACOSX) + auto synthetic_pinch_gesture = + std::make_unique<SyntheticTouchpadPinchGesture>(params); +#else + auto synthetic_pinch_gesture = + std::make_unique<SyntheticTouchscreenPinchGesture>(params); +#endif + + // Send pinch gesture and verify we receive the ack. + InputEventAckWaiter ack_waiter(host, blink::WebInputEvent::kGesturePinchEnd); + host->QueueSyntheticGesture( + std::move(synthetic_pinch_gesture), + base::BindOnce([](SyntheticGesture::Result result) { + EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result); + })); + ack_waiter.Wait(); + + // Make sure all the page scale values behave as expected. + const float kScaleTolerance = 0.0001f; + observer_a.WaitForPageScaleFactor(target_page_scale, kScaleTolerance); + observer_b.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); + observer_c.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); + observer_d.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); +} + // Verify that sandbox flags specified by a CSP header are properly inherited by // child frames, but are removed when the frame navigates. IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 892a3f93..7707451 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -674,14 +674,37 @@ // that might otherwise cause unpredictable behaviour in tests. class SystemEventRewriter : public ui::EventRewriter { public: + // Helper class to allow events to pass through for the lifetime of the + // object. Use this when tests generate events. This is needed under mash + // because the generate events reach SystemEventRewriter and will be dropped + // if there is no ScopedAllow instance. + // Note that allowing system events can cause flakiness in browser tests that + // don't expect them. + class ScopedAllow { + public: + explicit ScopedAllow(SystemEventRewriter* rewriter) : rewriter_(rewriter) { + ++rewriter_->num_of_scoped_allows_; + } + ~ScopedAllow() { + DCHECK_GT(rewriter_->num_of_scoped_allows_, 0); + --rewriter_->num_of_scoped_allows_; + } + + private: + SystemEventRewriter* const rewriter_; + + DISALLOW_COPY_AND_ASSIGN(ScopedAllow); + }; + SystemEventRewriter() = default; - ~SystemEventRewriter() override {} + ~SystemEventRewriter() override = default; private: ui::EventRewriteStatus RewriteEvent( const ui::Event& event, std::unique_ptr<ui::Event>* new_event) override { - return ui::EVENT_REWRITE_DISCARD; + return num_of_scoped_allows_ ? ui::EVENT_REWRITE_CONTINUE + : ui::EVENT_REWRITE_DISCARD; } ui::EventRewriteStatus NextDispatchEvent( @@ -691,6 +714,10 @@ return ui::EVENT_REWRITE_CONTINUE; } + // Count of ScopedAllow objects. When it is greater than 0, events are allowed + // to pass. Otherwise, they are discarded. + int num_of_scoped_allows_ = 0; + DISALLOW_COPY_AND_ASSIGN(SystemEventRewriter); }; #endif @@ -707,11 +734,11 @@ void PreRunTestOnMainThread() override { SitePerProcessBrowserTest::PreRunTestOnMainThread(); // Disable system mouse events, which can interfere with tests. - shell()->window()->GetHost()->AddEventRewriter(&event_rewriter); + shell()->window()->GetHost()->AddEventRewriter(&event_rewriter_); } void PostRunTestOnMainThread() override { - shell()->window()->GetHost()->RemoveEventRewriter(&event_rewriter); + shell()->window()->GetHost()->RemoveEventRewriter(&event_rewriter_); SitePerProcessBrowserTest::PostRunTestOnMainThread(); } #endif @@ -732,7 +759,7 @@ base::test::ScopedFeatureList feature_list_; #if defined(USE_AURA) - SystemEventRewriter event_rewriter; + SystemEventRewriter event_rewriter_; #endif }; @@ -3671,6 +3698,10 @@ InputEventAckWaiter ack_waiter(child_frame_host->GetRenderWidgetHost(), blink::WebInputEvent::kGestureTap); +#if defined(USE_AURA) + // Allows the gesture events to go through under mash. + SystemEventRewriter::ScopedAllow scoped_allow(&event_rewriter_); +#endif render_widget_host->QueueSyntheticGesture( std::move(gesture), base::BindOnce([](SyntheticGesture::Result result) { EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result); @@ -4688,9 +4719,10 @@ // On Mac and Android, the reported menu coordinates are relative to the // OOPIF, and its screen position is computed later, so this test isn't // relevant on those platforms. +// TODO(crbug.com/889002): This test is flaky. #if !defined(OS_ANDROID) && !defined(OS_MACOSX) IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, - ScrolledNestedPopupMenuTest) { + DISABLED_ScrolledNestedPopupMenuTest) { GURL main_url(embedded_test_server()->GetURL( "a.com", "/frame_tree/page_with_tall_positioned_frame.html")); EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index ffb6eb9..65173b2e 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2025,8 +2025,9 @@ bool request_to_lock_mouse_called_ = false; }; +// TODO(crbug.com/898641): This test is flaky. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, - RenderWidgetDeletedWhileMouseLockPending) { + DISABLED_RenderWidgetDeletedWhileMouseLockPending) { ASSERT_TRUE(embedded_test_server()->Start()); std::unique_ptr<MouseLockDelegate> delegate(new MouseLockDelegate());
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 6538fff..a4744fd 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -254,6 +254,7 @@ IPC_STRUCT_TRAITS_MEMBER(local_frame_size) IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) + IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) IPC_STRUCT_TRAITS_MEMBER(local_surface_id_allocation_time) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/frame_visual_properties.h b/content/common/frame_visual_properties.h index 7612cc6..4f5aa2a 100644 --- a/content/common/frame_visual_properties.h +++ b/content/common/frame_visual_properties.h
@@ -43,6 +43,8 @@ // (0 is the default value which results in 1.0 zoom factor.) double zoom_level = 0; + float page_scale_factor = 1.f; + // The time at which the viz::LocalSurfaceId used to submit this was // allocated. base::Optional<base::TimeTicks> local_surface_id_allocation_time;
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom index 6c17280..a5cc8524 100644 --- a/content/common/render_frame_metadata.mojom +++ b/content/common/render_frame_metadata.mojom
@@ -50,6 +50,11 @@ // The page scale factor used on the content. float page_scale_factor; + // The subframe page scale factor used on the content. This value will match + // |page_scale_factor|, which is only ever set for the main frame, and it is + // only used for setting raster scale in child renderers. + float external_page_scale_factor; + // Used to position the Android location top bar and page content, whose // precise position is computed by the renderer compositor. float top_controls_height;
diff --git a/content/common/render_frame_metadata_struct_traits.cc b/content/common/render_frame_metadata_struct_traits.cc index 781510cf..5ded5d9 100644 --- a/content/common/render_frame_metadata_struct_traits.cc +++ b/content/common/render_frame_metadata_struct_traits.cc
@@ -22,6 +22,7 @@ out->is_mobile_optimized = data.is_mobile_optimized(); out->device_scale_factor = data.device_scale_factor(); out->page_scale_factor = data.page_scale_factor(); + out->external_page_scale_factor = data.external_page_scale_factor(); out->top_controls_height = data.top_controls_height(); out->top_controls_shown_ratio = data.top_controls_shown_ratio(); #if defined(OS_ANDROID)
diff --git a/content/common/render_frame_metadata_struct_traits.h b/content/common/render_frame_metadata_struct_traits.h index cf07abc5..4b17453 100644 --- a/content/common/render_frame_metadata_struct_traits.h +++ b/content/common/render_frame_metadata_struct_traits.h
@@ -64,6 +64,11 @@ return metadata.page_scale_factor; } + static float external_page_scale_factor( + const cc::RenderFrameMetadata& metadata) { + return metadata.external_page_scale_factor; + } + static float top_controls_height(const cc::RenderFrameMetadata& metadata) { return metadata.top_controls_height; }
diff --git a/content/common/visual_properties.h b/content/common/visual_properties.h index aec8b24..3994dc0c 100644 --- a/content/common/visual_properties.h +++ b/content/common/visual_properties.h
@@ -82,6 +82,10 @@ // This represents the page zoom level for a WebContents. // (0 is the default value which results in 1.0 zoom factor). double zoom_level = 0; + + // This represents the page's scale factor, which changes during pinch zoom. + // It needs to be shared with subframes. + float page_scale_factor = 1.f; }; } // namespace content
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h index 1b8498ec..eac3448 100644 --- a/content/common/widget_messages.h +++ b/content/common/widget_messages.h
@@ -62,6 +62,7 @@ IPC_STRUCT_TRAITS_MEMBER(display_mode) IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) + IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) IPC_STRUCT_TRAITS_END() // Traits for WebDeviceEmulationParams. @@ -155,8 +156,9 @@ IPC_MESSAGE_ROUTED0(WidgetMsg_WasHidden) // Tells the render view that it is no longer hidden (see WasHidden). -IPC_MESSAGE_ROUTED1(WidgetMsg_WasShown, - base::TimeTicks /* show_request_timestamp */) +IPC_MESSAGE_ROUTED2(WidgetMsg_WasShown, + base::TimeTicks /* show_request_timestamp */, + bool /* was_evicted */) // Activate/deactivate the RenderWidget (i.e., set its controls' tint // accordingly, etc.).
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index f4b8f5aa..01be49a 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -70,6 +70,7 @@ "//net/android:net_java", "//services/device:java", "//services/device/public/java:nfc_java", + "//services/media_session/public/cpp/android:media_session_java", "//services/service_manager/public/java:service_manager_java", "//services/service_manager/public/mojom:mojom_java", "//services/shape_detection:shape_detection_java", @@ -275,7 +276,6 @@ "java/src/org/chromium/content_public/common/ContentProcessInfo.java", "java/src/org/chromium/content_public/common/ContentSwitches.java", "java/src/org/chromium/content_public/common/ContentUrlConstants.java", - "java/src/org/chromium/content_public/common/MediaMetadata.java", "java/src/org/chromium/content_public/common/Referrer.java", "java/src/org/chromium/content_public/common/ResourceRequestBody.java", "java/src/org/chromium/content_public/common/ScreenOrientationConstants.java", @@ -399,7 +399,6 @@ "java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java", "java/src/org/chromium/content/common/ServiceManagerConnectionImpl.java", "java/src/org/chromium/content_public/browser/LoadUrlParams.java", - "java/src/org/chromium/content_public/common/MediaMetadata.java", "java/src/org/chromium/content_public/common/ResourceRequestBody.java", "java/src/org/chromium/content_public/common/UseZoomForDSFPolicy.java", ]
diff --git a/content/public/android/DEPS b/content/public/android/DEPS index bc863f3..a51d6e2 100644 --- a/content/public/android/DEPS +++ b/content/public/android/DEPS
@@ -9,4 +9,6 @@ "+device", # Needed for implementing Device Service public component in java. "+services/device/public/java", + # Needed for implementing Media Session on Android. + "+services/media_session/public", ]
diff --git a/content/public/android/java/src/org/chromium/content/browser/MediaSessionImpl.java b/content/public/android/java/src/org/chromium/content/browser/MediaSessionImpl.java index a88cd28..09564b4a 100644 --- a/content/public/android/java/src/org/chromium/content/browser/MediaSessionImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/MediaSessionImpl.java
@@ -10,7 +10,7 @@ import org.chromium.content_public.browser.MediaSession; import org.chromium.content_public.browser.MediaSessionObserver; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.HashSet;
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/MediaSessionObserver.java b/content/public/android/java/src/org/chromium/content_public/browser/MediaSessionObserver.java index 83ecd40..39af3803 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/MediaSessionObserver.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/MediaSessionObserver.java
@@ -7,7 +7,7 @@ import android.support.annotation.Nullable; import org.chromium.content.browser.MediaSessionImpl; -import org.chromium.content_public.common.MediaMetadata; +import org.chromium.services.media_session.MediaMetadata; import java.util.Set;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 95eec34..94df084 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -642,7 +642,7 @@ #if defined(OS_CHROMEOS) // Notification that a trust anchor was used by the given user. - virtual void OnUsedTrustAnchor(const std::string& username_hash) {} + virtual void OnTrustAnchorUsed(const std::string& username_hash) {} #endif // Allows the embedder to override the LocationProvider implementation.
diff --git a/content/public/browser/site_isolation_policy.cc b/content/public/browser/site_isolation_policy.cc index ceedf96..f3e18cf 100644 --- a/content/public/browser/site_isolation_policy.cc +++ b/content/public/browser/site_isolation_policy.cc
@@ -35,7 +35,7 @@ } if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)) { + switches::kDisableSiteIsolation)) { return false; } @@ -80,7 +80,7 @@ } if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)) { + switches::kDisableSiteIsolation)) { return false; } @@ -122,7 +122,7 @@ // --isolate-origins (both command-line flag and enterprise policy) trumps // the opt-out flag. if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSiteIsolationTrials)) { + switches::kDisableSiteIsolation)) { return origins; }
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 3bd6767..202531dd 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -778,8 +778,18 @@ // process consolidation, not isolation). You probably want this one. const char kSitePerProcess[] = "site-per-process"; -// Disables enabling site isolation (i.e., --site-per-process) via field trial. -const char kDisableSiteIsolationTrials[] = "disable-site-isolation-trials"; +// Disables site isolation. +// +// Note that the opt-in (to site-per-process, isolate-origins, etc.) via +// enterprise policy and/or cmdline takes precedence over the +// kDisableSiteIsolation switch (i.e. the opt-in takes effect despite potential +// presence of kDisableSiteIsolation switch). +// +// Note that for historic reasons the name of the switch misleadingly mentions +// "trials", but the switch also disables the default site isolation that ships +// on desktop since M67. The name of the switch is preserved for +// backcompatibility of chrome://flags. +const char kDisableSiteIsolation[] = "disable-site-isolation-trials"; // Specifies if the browser should start in fullscreen mode, like if the user // had pressed F11 right after startup.
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index f5815a0..91691fb 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -218,7 +218,7 @@ extern const char kShowPaintRects[]; CONTENT_EXPORT extern const char kSingleProcess[]; CONTENT_EXPORT extern const char kSitePerProcess[]; -CONTENT_EXPORT extern const char kDisableSiteIsolationTrials[]; +CONTENT_EXPORT extern const char kDisableSiteIsolation[]; CONTENT_EXPORT extern const char kStartFullscreen[]; CONTENT_EXPORT extern const char kStatsCollectionController[]; extern const char kSkiaFontCacheLimitMb[];
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 9079f5d..33e58d0 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -2341,6 +2341,26 @@ Wait(); } +void RenderFrameSubmissionObserver::WaitForPageScaleFactor( + float expected_page_scale_factor, + const float tolerance) { + while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata() + .page_scale_factor - + expected_page_scale_factor) < tolerance) { + WaitForMetadataChange(); + } +} + +void RenderFrameSubmissionObserver::WaitForExternalPageScaleFactor( + float expected_external_page_scale_factor, + const float tolerance) { + while (std::abs(render_frame_metadata_provider_->LastRenderFrameMetadata() + .external_page_scale_factor - + expected_external_page_scale_factor) < tolerance) { + WaitForMetadataChange(); + } +} + void RenderFrameSubmissionObserver::WaitForScrollOffset( const gfx::Vector2dF& expected_offset) { while (render_frame_metadata_provider_->LastRenderFrameMetadata()
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index f12fc43f..a5caf75c 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1111,6 +1111,16 @@ // OnRenderFrameMetadataChangedAfterActivation. void WaitForMetadataChange(); + // Blocks the browser ui thread until RenderFrameMetadata arrives with + // page scale factor matching |expected_page_scale_factor|. + void WaitForPageScaleFactor(float expected_page_scale_factor, + const float tolerance); + + // Blocks the browser ui thread until RenderFrameMetadata arrives with + // external page scale factor matching |expected_external_page_scale_factor|. + void WaitForExternalPageScaleFactor(float expected_external_page_scale_factor, + const float tolerance); + // Blocks the browser ui thread until RenderFrameMetadata arrives where its // scroll offset matches |expected_offset|. void WaitForScrollOffset(const gfx::Vector2dF& expected_offset);
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc index 09afb40..c554efa 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -228,7 +228,8 @@ } void SynchronousLayerTreeFrameSink::SubmitCompositorFrame( - viz::CompositorFrame frame) { + viz::CompositorFrame frame, + bool show_hit_test_borders) { DCHECK(CalledOnValidThread()); DCHECK(sync_client_);
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.h b/content/renderer/android/synchronous_layer_tree_frame_sink.h index 5177e34..b3db8ad0 100644 --- a/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/content/renderer/android/synchronous_layer_tree_frame_sink.h
@@ -91,7 +91,8 @@ // cc::LayerTreeFrameSink implementation. bool BindToClient(cc::LayerTreeFrameSinkClient* sink_client) override; void DetachFromClient() override; - void SubmitCompositorFrame(viz::CompositorFrame frame) override; + void SubmitCompositorFrame(viz::CompositorFrame frame, + bool show_hit_test_borders) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) override;
diff --git a/content/renderer/gpu/layer_tree_view.cc b/content/renderer/gpu/layer_tree_view.cc index 8db392f..ca1cc944 100644 --- a/content/renderer/gpu/layer_tree_view.cc +++ b/content/renderer/gpu/layer_tree_view.cc
@@ -702,6 +702,10 @@ layer_tree_host_->SetRasterColorSpace(color_space); } +void LayerTreeView::SetExternalPageScaleFactor(float page_scale_factor) { + layer_tree_host_->SetExternalPageScaleFactor(page_scale_factor); +} + void LayerTreeView::ClearCachesOnNextCommit() { layer_tree_host_->ClearCachesOnNextCommit(); } @@ -753,4 +757,8 @@ layer_tree_host_->SetURLForUkm(url); } +void LayerTreeView::ReleaseLayerTreeFrameSink() { + layer_tree_host_->ReleaseLayerTreeFrameSink(); +} + } // namespace content
diff --git a/content/renderer/gpu/layer_tree_view.h b/content/renderer/gpu/layer_tree_view.h index 585c67e..97f925a 100644 --- a/content/renderer/gpu/layer_tree_view.h +++ b/content/renderer/gpu/layer_tree_view.h
@@ -107,6 +107,7 @@ bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value); void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id); void SetRasterColorSpace(const gfx::ColorSpace& color_space); + void SetExternalPageScaleFactor(float page_scale_factor); void ClearCachesOnNextCommit(); void SetContentSourceId(uint32_t source_id); void SetViewportSizeAndScale(const gfx::Size& device_viewport_size, @@ -116,6 +117,12 @@ void RequestNewLocalSurfaceId(); void SetViewportVisibleRect(const gfx::Rect& visible_rect); void SetURLForUkm(const GURL& url); + // Call this if the compositor is becoming non-visible in a way that it won't + // be used any longer. In this case, becoming visible is longer but this + // releases more resources (such as its use of the GpuChannel). + // TODO(crbug.com/419087): This is to support a swapped out RenderWidget which + // should just be destroyed instead. + void ReleaseLayerTreeFrameSink(); // blink::WebLayerTreeView implementation. viz::FrameSinkId GetFrameSinkId() override;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc index a95e495..29082a4 100644 --- a/content/renderer/render_frame_impl_browsertest.cc +++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -211,7 +211,8 @@ TEST_F(RenderFrameImplTest, FrameWasShown) { RenderFrameTestObserver observer(frame()); - WidgetMsg_WasShown was_shown_message(0, base::TimeTicks()); + WidgetMsg_WasShown was_shown_message(0, base::TimeTicks(), + false /* was_evicted */); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden()); @@ -241,7 +242,8 @@ RenderFrameTestObserver observer(grandchild); - WidgetMsg_WasShown was_shown_message(0, base::TimeTicks()); + WidgetMsg_WasShown was_shown_message(0, base::TimeTicks(), + false /* was_evicted */); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden()); @@ -254,7 +256,8 @@ WidgetMsg_Close close_message(0); frame_widget()->OnMessageReceived(close_message); - WidgetMsg_WasShown was_shown_message(0, base::TimeTicks()); + WidgetMsg_WasShown was_shown_message(0, base::TimeTicks(), + false /* was_evicted */); // Test passes if this does not crash. RenderWidget* render_widget = static_cast<RenderViewImpl*>(view_)->GetWidget();
diff --git a/content/renderer/render_frame_metadata_observer_impl.cc b/content/renderer/render_frame_metadata_observer_impl.cc index b98aa7b..590ec653 100644 --- a/content/renderer/render_frame_metadata_observer_impl.cc +++ b/content/renderer/render_frame_metadata_observer_impl.cc
@@ -113,6 +113,7 @@ rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top || rfm1.selection != rfm2.selection || rfm1.page_scale_factor != rfm2.page_scale_factor || + rfm1.external_page_scale_factor != rfm2.external_page_scale_factor || rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || rfm1.device_scale_factor != rfm2.device_scale_factor || rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels ||
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 21cba8c..c2b014f8 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -295,6 +295,11 @@ SynchronizeVisualProperties(); } +void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor) { + pending_visual_properties_.page_scale_factor = page_scale_factor; + SynchronizeVisualProperties(); +} + void RenderFrameProxy::UpdateCaptureSequenceNumber( uint32_t capture_sequence_number) { pending_visual_properties_.capture_sequence_number = capture_sequence_number; @@ -652,6 +657,8 @@ pending_visual_properties_.screen_info || sent_visual_properties_->zoom_level != pending_visual_properties_.zoom_level || + sent_visual_properties_->page_scale_factor != + pending_visual_properties_.page_scale_factor || capture_sequence_number_changed; if (synchronized_props_changed) { @@ -936,4 +943,10 @@ return parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); } +void RenderFrameProxy::WasEvicted() { + // On eviction, the last SurfaceId is invalidated. We need to allocate a new + // id. + ResendVisualProperties(); +} + } // namespace content
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index f399249b..bf8b25df 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -139,6 +139,10 @@ // zoom level has changed. void OnZoomLevelChanged(double zoom_level); + // Out-of-process child frames receive a signal from RenderWidget when the + // page scale factor has changed. + void OnPageScaleFactorChanged(float page_scale_factor); + // Invoked by RenderWidget when a new capture sequence number was set, // indicating that surfaces should be synchronized. void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number); @@ -213,6 +217,8 @@ // IPC handlers void OnDidStartLoading(); + void WasEvicted(); + private: RenderFrameProxy(int routing_id);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index c5f15ce..9385535 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1091,6 +1091,12 @@ void RenderViewImpl::OverrideCloseForWidget() { DCHECK(frame_widget_); + // The RenderWidget isn't actually closed here because we might need to use it + // again since it can't be recreated as it is part of |this|. So instead just + // stop the compositor. + // TODO(crbug.com/419087): The RenderWidget should be destroyed here along + // with the WebFrameWidget, then we won't have to do this. + GetWidget()->StopCompositor(); frame_widget_->Close(); frame_widget_ = nullptr; } @@ -1537,6 +1543,12 @@ // The previous WebFrameWidget must already be detached by CloseForFrame(). DCHECK(!frame_widget_); frame_widget_ = frame_widget; + // In CloseForFrame() the RenderWidget's compositor was stopped instead of + // deleting the RenderWidget. So here we can start it again. For the first + // main frame, it would already be started by default so this does nothing. + // TODO(crbug.com/419087): The RenderWidget should be newly created here along + // with the WebFrameWidget, then we won't have to do this. + GetWidget()->StartCompositor(); } void RenderViewImpl::SetZoomLevel(double zoom_level) { @@ -2040,6 +2052,7 @@ Send(new ViewHostMsg_PageScaleFactorChanged(GetRoutingID(), webview()->PageScaleFactor())); + GetWidget()->PageScaleFactorChanged(webview()->PageScaleFactor()); } double RenderViewImpl::zoomLevelToZoomFactor(double zoom_level) const {
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 9859aa5..0abf0a90 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -783,6 +783,7 @@ visual_properties.visible_viewport_size = visible_viewport_size_; visual_properties.is_fullscreen_granted = is_fullscreen_granted_; visual_properties.display_mode = display_mode_; + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; screen_metrics_emulator_.reset(new RenderWidgetScreenMetricsEmulator( this, params, visual_properties, widget_screen_rect_, window_screen_rect_)); @@ -804,7 +805,8 @@ observer.WasHidden(); } -void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp) { +void RenderWidget::OnWasShown(base::TimeTicks show_request_timestamp, + bool was_evicted) { TRACE_EVENT0("renderer", "RenderWidget::OnWasShown"); // During shutdown we can just ignore this message. if (!GetWebWidget()) @@ -816,6 +818,12 @@ for (auto& observer : render_frames_) observer.WasShown(); + if (was_evicted) { + for (auto& observer : render_frame_proxies_) { + observer.WasEvicted(); + } + } + if (layer_tree_view_ && !show_request_timestamp.is_null()) { layer_tree_view_->layer_tree_host()->RequestPresentationTimeForNextFrame( CreateTabSwitchingTimeRecorder(show_request_timestamp)); @@ -1337,6 +1345,10 @@ if (!GetWebWidget()) return; + // Only propagate the external PSF to non-main-frames. + if (!owner_delegate_) + layer_tree_view_->SetExternalPageScaleFactor(params.page_scale_factor); + gfx::Size new_compositor_viewport_pixel_size = params.auto_resize_enabled ? gfx::ScaleToCeiledSize(size_, @@ -1384,6 +1396,14 @@ if (fullscreen_change) DidToggleFullscreen(); + + if (!owner_delegate_) { + // Make sure that page scale factor changes propagating down from the main + // frame are relayed to nested OOPIFs/non-main-frames. + page_scale_factor_from_mainframe_ = params.page_scale_factor; + for (auto& observer : render_frame_proxies_) + observer.OnPageScaleFactorChanged(params.page_scale_factor); + } } void RenderWidget::SetScreenMetricsEmulationParameters( @@ -1548,10 +1568,17 @@ // LayerTreeFrameSink creation. bool should_generate_frame_sink = !compositor_never_visible_ && RenderThreadImpl::current(); - if (!should_generate_frame_sink) + if (!should_generate_frame_sink) { + // Prevents SetVisible() from blink from doing anything. layer_tree_view_->SetNeverVisible(); + } else if (!is_swapped_out_) { + // Begins the compositor's scheduler to start producing frames. + // Don't do this if the RenderWidget is attached to a RenderViewImpl for a + // remote main frame, as this RenderWidget is a zombie then, which won't be + // used for compositing until a WebFrameWidget is attached. + StartCompositor(); + } - StartCompositor(); DCHECK_NE(MSG_ROUTING_NONE, routing_id_); layer_tree_view_->SetFrameSinkId( viz::FrameSinkId(RenderThread::Get()->GetClientId(), routing_id_)); @@ -1918,6 +1945,7 @@ visual_properties.is_fullscreen_granted = is_fullscreen_granted_; visual_properties.display_mode = display_mode_; visual_properties.local_surface_id = local_surface_id_from_parent_; + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; // We are resizing the window from the renderer, so allocate a new // viz::LocalSurfaceId to avoid surface invariants violations in tests. if (layer_tree_view_) @@ -2889,10 +2917,19 @@ } void RenderWidget::StartCompositor() { - if (!is_hidden()) + if (!is_hidden_) layer_tree_view_->SetVisible(true); } +void RenderWidget::StopCompositor() { + layer_tree_view_->SetVisible(false); + // Drop all gpu resources, this makes SetVisible(true) more expensive/slower + // but we don't expect to use this RenderWidget again until some possible + // future navigation. This brings us a bit closer to emulating deleting the + // RenderWidget instead of just stopping the compositor. + layer_tree_view_->ReleaseLayerTreeFrameSink(); +} + void RenderWidget::HasPointerRawMoveEventHandlers(bool has_handlers) { if (input_event_queue_) input_event_queue_->HasPointerRawMoveEventHandlers(has_handlers); @@ -2927,6 +2964,10 @@ void RenderWidget::RegisterRenderFrameProxy(RenderFrameProxy* proxy) { render_frame_proxies_.AddObserver(proxy); + // During initial page load, the main frame may have received page + // scale factor information before the sub-frame proxies were registered, so + // make sure we pass the page scale factor along here. + proxy->OnPageScaleFactorChanged(page_scale_factor_from_mainframe_); } void RenderWidget::UnregisterRenderFrameProxy(RenderFrameProxy* proxy) { @@ -3068,6 +3109,18 @@ layer_tree_view_->IsSurfaceSynchronizationEnabled(); } +void RenderWidget::PageScaleFactorChanged(float page_scale_factor) { + // Only the main frame pulls page scale information from the layer tree host. + // Pages scale is shared with non-mainframe widgets via the IPC for + // OnSynchronizeVisualProperties. + if (!owner_delegate_) + return; + + page_scale_factor_from_mainframe_ = page_scale_factor; + for (auto& observer : render_frame_proxies_) + observer.OnPageScaleFactorChanged(page_scale_factor); +} + void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) { resizing_mode_selector_->set_is_synchronous_mode(enable); } @@ -3087,6 +3140,7 @@ visual_properties.is_fullscreen_granted = is_fullscreen_granted_; visual_properties.display_mode = display_mode_; visual_properties.local_surface_id = local_surface_id_from_parent_; + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; // We are changing the device scale factor from the renderer, so allocate a // new viz::LocalSurfaceId to avoid surface invariants violations in tests. if (layer_tree_view_) @@ -3109,6 +3163,7 @@ visual_properties.is_fullscreen_granted = is_fullscreen_granted_; visual_properties.display_mode = display_mode_; visual_properties.local_surface_id = local_surface_id_from_parent_; + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; // We are changing the device color space from the renderer, so allocate a // new viz::LocalSurfaceId to avoid surface invariants violations in tests. if (layer_tree_view_) @@ -3129,6 +3184,7 @@ visual_properties.max_size_for_auto_resize = max_size; visual_properties.local_surface_id = base::Optional<viz::LocalSurfaceId>( viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create())); + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; OnSynchronizeVisualProperties(visual_properties); } @@ -3148,6 +3204,7 @@ visual_properties.visible_viewport_size = visible_viewport_size_; visual_properties.is_fullscreen_granted = is_fullscreen_granted_; visual_properties.display_mode = display_mode_; + visual_properties.page_scale_factor = page_scale_factor_from_mainframe_; OnSynchronizeVisualProperties(visual_properties); }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 27e1d98..e5845ae3 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -343,25 +343,20 @@ // position. ui::TextInputType GetTextInputType(); - // Internal helper that generates the LayerTreeSettings to be given to the - // compositor in StartCompositor(). static cc::LayerTreeSettings GenerateLayerTreeSettings( CompositorDependencies* compositor_deps, bool is_for_subframe, const gfx::Size& initial_screen_size, float initial_device_scale_factor); - // Internal helper that generates the ManagedMemoryPolicy to be given to the - // compositor in StartCompositor(). static cc::ManagedMemoryPolicy GetGpuMemoryPolicy( const cc::ManagedMemoryPolicy& policy, const gfx::Size& initial_screen_size, float initial_device_scale_factor); - // Begins the compositor's scheduler to start producing frames. + // Initiates the compositor to set up IPC channels and begin its scheduler. void StartCompositor(); - - // Stop compositing. - void WillCloseLayerTreeView(); + // Pauses the compositor's scheduler and tears down its IPC channels. + void StopCompositor(); LayerTreeView* layer_tree_view() const { return layer_tree_view_.get(); } WidgetInputHandlerManager* widget_input_handler_manager() { @@ -510,6 +505,8 @@ bool IsSurfaceSynchronizationEnabled() const; + void PageScaleFactorChanged(float page_scale_factor); + void UseSynchronousResizeModeForTesting(bool enable); void SetDeviceScaleFactorForTesting(float factor); void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space); @@ -571,6 +568,9 @@ // It is safe to call this multiple times, which happens in the case of // frame widgets beings closed, since subsequent calls are ignored. void CloseWebWidget(); + // Informs the WebWidget that compositor is being destroyed, so it can remove + // references to it first. + void WillCloseLayerTreeView(); #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) void SetExternalPopupOriginAdjustmentsForEmulation( @@ -589,7 +589,7 @@ void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params); void OnDisableDeviceEmulation(); void OnWasHidden(); - void OnWasShown(base::TimeTicks show_request_timestamp); + void OnWasShown(base::TimeTicks show_request_timestamp, bool was_evicted); void OnCreateVideoAck(int32_t video_id); void OnUpdateVideoAck(int32_t video_id); void OnRequestSetBoundsAck(); @@ -944,6 +944,10 @@ // The height of the browser bottom controls. float bottom_controls_height_ = 0.f; + // The page scale factor reported by the main-frame's RenderWidget, via + // SynchronizeVisualProperties. + float page_scale_factor_from_mainframe_ = 1.f; + // This is initialized to zero and is incremented on each non-same-page // navigation commit by RenderFrameImpl. At that time it is sent to the // compositor so that it can tag compositor frames, and RenderFrameImpl is
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc index eea70a0..1f32e9a 100644 --- a/content/shell/browser/shell_devtools_bindings.cc +++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -77,9 +77,9 @@ request_id_(request_id), bindings_(bindings), loader_(std::move(loader)) { - loader_->DownloadAsStream(url_loader_factory, this); loader_->SetOnResponseStartedCallback(base::BindOnce( &NetworkResourceLoader::OnResponseStarted, base::Unretained(this))); + loader_->DownloadAsStream(url_loader_factory, this); } private:
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 3fdd208..17b4c26a 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -731,19 +731,18 @@ self.Skip('conformance/textures/misc/texture-npot-video.html', ['android', 'android-webview-instrumentation', 'no_passthrough'], bug=352645) - # New video-to-luminance-alpha tests are failing on Android right now. - self.Fail('conformance/textures/video/' + - 'tex-2d-alpha-alpha-unsigned_byte.html', - ['android'], bug=733599) - self.Fail('conformance/textures/video/' + - 'tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html', - ['android'], bug=733599) - self.Fail('conformance/textures/video/' + - 'tex-2d-luminance-luminance-unsigned_byte.html', - ['android'], bug=733599) # These video tests appear to be flaky. self.Flaky('conformance/textures/video/' + + 'tex-2d-alpha-alpha-unsigned_byte.html', + ['android'], bug=733599) + self.Flaky('conformance/textures/video/' + + 'tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html', + ['android'], bug=733599) + self.Flaky('conformance/textures/video/' + + 'tex-2d-luminance-luminance-unsigned_byte.html', + ['android'], bug=733599) + self.Flaky('conformance/textures/video/' + 'tex-2d-rgb-rgb-unsigned_byte.html', ['android', 'android-chromium'], bug=834933) self.Flaky('conformance/textures/video/' +
diff --git a/gpu/command_buffer/service/copy_texture_chromium_mock.cc b/gpu/command_buffer/service/copy_texture_chromium_mock.cc index e09b612..a1ec4839 100644 --- a/gpu/command_buffer/service/copy_texture_chromium_mock.cc +++ b/gpu/command_buffer/service/copy_texture_chromium_mock.cc
@@ -7,6 +7,11 @@ namespace gpu { namespace gles2 { +MockCopyTexImageResourceManager::MockCopyTexImageResourceManager( + const gles2::FeatureInfo* feature_info) + : CopyTexImageResourceManager(feature_info) {} +MockCopyTexImageResourceManager::~MockCopyTexImageResourceManager() = default; + MockCopyTextureResourceManager::MockCopyTextureResourceManager() = default; MockCopyTextureResourceManager::~MockCopyTextureResourceManager() = default;
diff --git a/gpu/command_buffer/service/copy_texture_chromium_mock.h b/gpu/command_buffer/service/copy_texture_chromium_mock.h index af90c22..622cf5da 100644 --- a/gpu/command_buffer/service/copy_texture_chromium_mock.h +++ b/gpu/command_buffer/service/copy_texture_chromium_mock.h
@@ -5,12 +5,61 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_COPY_TEXTURE_CHROMIUM_MOCK_H_ #define GPU_COMMAND_BUFFER_SERVICE_COPY_TEXTURE_CHROMIUM_MOCK_H_ +#include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" + #include "testing/gmock/include/gmock/gmock.h" namespace gpu { namespace gles2 { +class MockCopyTexImageResourceManager : public CopyTexImageResourceManager { + public: + MockCopyTexImageResourceManager(const gles2::FeatureInfo* feature_info); + ~MockCopyTexImageResourceManager() final; + + MOCK_METHOD1(Initialize, void(const DecoderContext* decoder)); + MOCK_METHOD0(Destroy, void()); + + // Cannot MOCK_METHOD more than 10 args. + void DoCopyTexImage2DToLUMACompatibilityTexture( + const DecoderContext* decoder, + GLuint dest_texture, + GLenum dest_texture_target, + GLenum dest_target, + GLenum luma_format, + GLenum luma_type, + GLint level, + GLenum internal_format, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLuint source_framebuffer, + GLenum source_framebuffer_internal_format) override {} + + void DoCopyTexSubImageToLUMACompatibilityTexture( + const DecoderContext* decoder, + GLuint dest_texture, + GLenum dest_texture_target, + GLenum dest_target, + GLenum luma_format, + GLenum luma_type, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLuint source_framebuffer, + GLenum source_framebuffer_internal_format) override{}; + + private: + DISALLOW_COPY_AND_ASSIGN(MockCopyTexImageResourceManager); +}; + class MockCopyTextureResourceManager : public CopyTextureCHROMIUMResourceManager { public: @@ -110,6 +159,7 @@ bool unpremultiply_alpha, bool dither, const GLfloat transform_matrix[16], + CopyTextureMethod method, CopyTexImageResourceManager* luma_emulation_blitter) override{}; private:
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc index 2da3d7f8..5df356a 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc
@@ -9,13 +9,15 @@ #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_version_info.h" +#include <string> + namespace gpu { namespace gles2 { CopyTexImageResourceManager::CopyTexImageResourceManager( const gles2::FeatureInfo* feature_info) : feature_info_(feature_info) { - DCHECK(feature_info->gl_version_info().is_desktop_core_profile); + DCHECK(feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()); } CopyTexImageResourceManager::~CopyTexImageResourceManager() = default; @@ -28,8 +30,9 @@ blit_program_ = glCreateProgram(); // Compile the vertex shader - const char* vs_source = - "#version 150\n" + std::string vs_source = + std::string(feature_info_->gl_version_info().is_es3 ? "#version 300 es\n" + : "#version 150\n") + "out vec2 v_texcoord;\n" "\n" "void main()\n" @@ -51,13 +54,15 @@ "}\n"; GLuint vs = glCreateShader(GL_VERTEX_SHADER); - CompileShaderWithLog(vs, vs_source); + CompileShaderWithLog(vs, vs_source.c_str()); glAttachShader(blit_program_, vs); glDeleteShader(vs); // Compile the fragment shader - const char* fs_source = - "#version 150\n" + std::string fs_source = + std::string(feature_info_->gl_version_info().is_es3 + ? "#version 300 es\nprecision mediump float;\n" + : "#version 150\n") + "uniform sampler2D u_source_texture;\n" "in vec2 v_texcoord;\n" "out vec4 output_color;\n" @@ -68,7 +73,7 @@ "}\n"; GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - CompileShaderWithLog(fs, fs_source); + CompileShaderWithLog(fs, fs_source.c_str()); glAttachShader(blit_program_, fs); glDeleteShader(fs); @@ -192,7 +197,15 @@ (luma_format == GL_LUMINANCE_ALPHA) ? GL_ALPHA : GL_ZERO, GL_ZERO, GL_ZERO, }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + if (feature_info_->gl_version_info().is_es) { + // ES doesn't support GL_TEXTURE_SWIZZLE_RGBA. We must set each swizzle + // separately. + for (int i = 0; i < 4; i++) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R + i, swizzle[i]); + } + } else { + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); + } // Make a temporary framebuffer using the second scratch texture to render the // swizzled result to. @@ -254,7 +267,7 @@ bool CopyTexImageResourceManager::CopyTexImageRequiresBlit( const gles2::FeatureInfo* feature_info, GLenum dest_texture_format) { - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { switch (dest_texture_format) { case GL_LUMINANCE: case GL_ALPHA:
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h index fcffeba6..269cad6 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h +++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.h
@@ -10,7 +10,6 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "gpu/command_buffer/service/feature_info.h" -#include "gpu/command_buffer/service/gl_utils.h" #include "gpu/gpu_gles2_export.h" namespace gpu { @@ -24,12 +23,12 @@ class GPU_GLES2_EXPORT CopyTexImageResourceManager { public: explicit CopyTexImageResourceManager(const gles2::FeatureInfo* feature_info); - ~CopyTexImageResourceManager(); + virtual ~CopyTexImageResourceManager(); - void Initialize(const DecoderContext* decoder); - void Destroy(); + virtual void Initialize(const DecoderContext* decoder); + virtual void Destroy(); - void DoCopyTexImage2DToLUMACompatibilityTexture( + virtual void DoCopyTexImage2DToLUMACompatibilityTexture( const DecoderContext* decoder, GLuint dest_texture, GLenum dest_texture_target, @@ -45,7 +44,7 @@ GLuint source_framebuffer, GLenum source_framebuffer_internal_format); - void DoCopyTexSubImageToLUMACompatibilityTexture( + virtual void DoCopyTexSubImageToLUMACompatibilityTexture( const DecoderContext* decoder, GLuint dest_texture, GLenum dest_texture_target,
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc index a7e0c121..f5fbb9d 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -13,6 +13,7 @@ #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" +#include "ui/gl/gl_enums.h" #include "ui/gl/gl_version_info.h" namespace gpu { @@ -280,7 +281,8 @@ destFormatIndex = D_FORMAT_RGB10_A2; break; default: - NOTREACHED(); + NOTREACHED() << "Invalid destination format " + << gl::GLEnums::GetStringEnum(dest_format); break; } @@ -512,17 +514,22 @@ GLuint texture_id, GLint level, GLuint framebuffer) { - DCHECK(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB); + GLenum binding_target = + gpu::gles2::GLES2Util::GLFaceTargetToTextureTarget(target); + + DCHECK(binding_target == GL_TEXTURE_2D || + binding_target == GL_TEXTURE_RECTANGLE_ARB || + binding_target == GL_TEXTURE_CUBE_MAP); glActiveTexture(GL_TEXTURE0); - glBindTexture(target, texture_id); + glBindTexture(binding_target, texture_id); // NVidia drivers require texture settings to be a certain way // or they won't report FRAMEBUFFER_COMPLETE. if (level > 0) - glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, level); - glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(binding_target, GL_TEXTURE_BASE_LEVEL, level); + glTexParameterf(binding_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(binding_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(binding_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(binding_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture_id, level); @@ -936,6 +943,7 @@ bool unpremultiply_alpha, bool dither, const GLfloat transform_matrix[16], + CopyTextureMethod method, CopyTexImageResourceManager* luma_emulation_blitter) override; private: @@ -1107,63 +1115,12 @@ bool dither, CopyTextureMethod method, gpu::gles2::CopyTexImageResourceManager* luma_emulation_blitter) { - if (method == CopyTextureMethod::DIRECT_COPY) { - DoCopyTexImage2D(decoder, source_target, source_id, source_level, - source_internal_format, dest_target, dest_id, dest_level, - dest_internal_format, width, height, framebuffer_, - luma_emulation_blitter); - return; - } - - // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. - GLuint dest_texture = dest_id; - GLuint intermediate_texture = 0; - GLint original_dest_level = dest_level; - GLenum original_dest_target = dest_target; - GLenum original_internal_format = dest_internal_format; - if (method == CopyTextureMethod::DRAW_AND_COPY || - method == CopyTextureMethod::DRAW_AND_READBACK) { - GLenum adjusted_internal_format = - method == CopyTextureMethod::DRAW_AND_READBACK - ? GL_RGBA - : getIntermediateFormat(dest_internal_format); - dest_target = GL_TEXTURE_2D; - glGenTextures(1, &intermediate_texture); - glBindTexture(dest_target, intermediate_texture); - GLenum format = TextureManager::ExtractFormatFromStorageFormat( - adjusted_internal_format); - GLenum type = - TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); - - glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, - format, type, nullptr); - dest_texture = intermediate_texture; - dest_level = 0; - dest_internal_format = adjusted_internal_format; - } // Use kIdentityMatrix if no transform passed in. - DoCopyTextureWithTransform(decoder, source_target, source_id, source_level, - source_internal_format, dest_target, dest_texture, - dest_level, dest_internal_format, width, height, - flip_y, premultiply_alpha, unpremultiply_alpha, - dither, kIdentityMatrix, luma_emulation_blitter); - - if (method == CopyTextureMethod::DRAW_AND_COPY || - method == CopyTextureMethod::DRAW_AND_READBACK) { - source_level = 0; - if (method == CopyTextureMethod::DRAW_AND_COPY) { - DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level, - dest_internal_format, original_dest_target, dest_id, - original_dest_level, original_internal_format, width, - height, framebuffer_, luma_emulation_blitter); - } else if (method == CopyTextureMethod::DRAW_AND_READBACK) { - DoReadbackAndTexImage( - kTexImage, decoder, dest_target, intermediate_texture, source_level, - original_dest_target, dest_id, original_dest_level, - original_internal_format, 0, 0, width, height, framebuffer_); - } - glDeleteTextures(1, &intermediate_texture); - } + DoCopyTextureWithTransform( + decoder, source_target, source_id, source_level, source_internal_format, + dest_target, dest_id, dest_level, dest_internal_format, width, height, + flip_y, premultiply_alpha, unpremultiply_alpha, dither, kIdentityMatrix, + method, luma_emulation_blitter); } void CopyTextureResourceManagerImpl::DoCopySubTexture( @@ -1299,11 +1256,11 @@ GLenum source_target, GLuint source_id, GLint source_level, - GLenum source_format, + GLenum source_internal_format, GLenum dest_target, GLuint dest_id, GLint dest_level, - GLenum dest_format, + GLenum dest_internal_format, GLsizei width, GLsizei height, bool flip_y, @@ -1311,14 +1268,67 @@ bool unpremultiply_alpha, bool dither, const GLfloat transform_matrix[16], + CopyTextureMethod method, gpu::gles2::CopyTexImageResourceManager* luma_emulation_blitter) { GLsizei dest_width = width; GLsizei dest_height = height; - DoCopyTextureInternal( - decoder, source_target, source_id, source_level, source_format, - dest_target, dest_id, dest_level, dest_format, 0, 0, 0, 0, width, height, - dest_width, dest_height, width, height, flip_y, premultiply_alpha, - unpremultiply_alpha, dither, transform_matrix, luma_emulation_blitter); + if (method == CopyTextureMethod::DIRECT_COPY) { + DoCopyTexImage2D(decoder, source_target, source_id, source_level, + source_internal_format, dest_target, dest_id, dest_level, + dest_internal_format, width, height, framebuffer_, + luma_emulation_blitter); + return; + } + + // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. + GLuint dest_texture = dest_id; + GLint original_dest_level = dest_level; + GLenum original_dest_target = dest_target; + GLuint intermediate_texture = 0; + GLenum original_internal_format = dest_internal_format; + if (method == CopyTextureMethod::DRAW_AND_COPY || + method == CopyTextureMethod::DRAW_AND_READBACK) { + GLenum adjusted_internal_format = + method == CopyTextureMethod::DRAW_AND_READBACK + ? GL_RGBA + : getIntermediateFormat(dest_internal_format); + dest_target = GL_TEXTURE_2D; + glGenTextures(1, &intermediate_texture); + glBindTexture(dest_target, intermediate_texture); + GLenum format = TextureManager::ExtractFormatFromStorageFormat( + adjusted_internal_format); + GLenum type = + TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); + glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, + format, type, nullptr); + dest_texture = intermediate_texture; + dest_level = 0; + dest_internal_format = adjusted_internal_format; + } + + DoCopyTextureInternal(decoder, source_target, source_id, source_level, + source_internal_format, dest_target, dest_texture, + dest_level, dest_internal_format, 0, 0, 0, 0, width, + height, dest_width, dest_height, width, height, flip_y, + premultiply_alpha, unpremultiply_alpha, dither, + transform_matrix, luma_emulation_blitter); + + if (method == CopyTextureMethod::DRAW_AND_COPY || + method == CopyTextureMethod::DRAW_AND_READBACK) { + source_level = 0; + if (method == CopyTextureMethod::DRAW_AND_COPY) { + DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level, + dest_internal_format, original_dest_target, dest_id, + original_dest_level, original_internal_format, width, + height, framebuffer_, luma_emulation_blitter); + } else if (method == CopyTextureMethod::DRAW_AND_READBACK) { + DoReadbackAndTexImage( + kTexSubImage, decoder, dest_target, intermediate_texture, + source_level, original_dest_target, dest_id, original_dest_level, + original_internal_format, 0, 0, width, height, framebuffer_); + } + glDeleteTextures(1, &intermediate_texture); + } } void CopyTextureResourceManagerImpl::DoCopyTextureInternal( @@ -1351,7 +1361,9 @@ source_target == GL_TEXTURE_RECTANGLE_ARB || source_target == GL_TEXTURE_EXTERNAL_OES); DCHECK(dest_target == GL_TEXTURE_2D || - dest_target == GL_TEXTURE_RECTANGLE_ARB); + dest_target == GL_TEXTURE_RECTANGLE_ARB || + (dest_target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && + dest_target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)); DCHECK_GE(source_level, 0); DCHECK_GE(dest_level, 0); DCHECK_GE(xoffset, 0);
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h index 97ef432..bc9ec51 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h
@@ -151,6 +151,7 @@ bool unpremultiply_alpha, bool dither, const GLfloat transform_matrix[16], + CopyTextureMethod method, CopyTexImageResourceManager* luma_emulation_blitter) = 0; // The attributes used during invocation of the extension.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6395b503..7c9aeb85 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -782,6 +782,11 @@ copy_texture_chromium_.reset(copy_texture_resource_manager); } + void SetCopyTexImageBlitterForTest( + CopyTexImageResourceManager* copy_tex_image_blit) override { + copy_tex_image_blit_.reset(copy_tex_image_blit); + } + // ServiceFontManager::Client implementation. scoped_refptr<gpu::Buffer> GetShmBuffer(uint32_t shm_id); @@ -17052,6 +17057,12 @@ DoBindOrCopyTexImageIfNeeded(source_texture, source_target, 0); + CopyTextureMethod method = GetCopyTextureCHROMIUMMethod( + GetFeatureInfo(), source_target, source_level, source_internal_format, + source_type, dest_binding_target, dest_level, internal_format, + unpack_flip_y == GL_TRUE, unpack_premultiply_alpha == GL_TRUE, + unpack_unmultiply_alpha == GL_TRUE, false /* dither */); + // GL_TEXTURE_EXTERNAL_OES texture requires that we apply a transform matrix // before presenting. if (source_target == GL_TEXTURE_EXTERNAL_OES) { @@ -17066,16 +17077,10 @@ dest_level, internal_format, source_width, source_height, unpack_flip_y == GL_TRUE, unpack_premultiply_alpha == GL_TRUE, unpack_unmultiply_alpha == GL_TRUE, false /* dither */, - transform_matrix, copy_tex_image_blit_.get()); + transform_matrix, method, copy_tex_image_blit_.get()); return; } } - - CopyTextureMethod method = GetCopyTextureCHROMIUMMethod( - GetFeatureInfo(), source_target, source_level, source_internal_format, - source_type, dest_binding_target, dest_level, internal_format, - unpack_flip_y == GL_TRUE, unpack_premultiply_alpha == GL_TRUE, - unpack_unmultiply_alpha == GL_TRUE, false /* dither */); copy_texture_chromium_->DoCopyTexture( this, source_target, source_texture->service_id(), source_level, source_internal_format, dest_target, dest_texture->service_id(),
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index f9bae4e..01be2ce 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -42,6 +42,7 @@ namespace gles2 { class ContextGroup; +class CopyTexImageResourceManager; class CopyTextureCHROMIUMResourceManager; class FramebufferManager; class GLES2Util; @@ -182,6 +183,9 @@ virtual void SetCopyTextureResourceManagerForTest( CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager) = 0; + virtual void SetCopyTexImageBlitterForTest( + CopyTexImageResourceManager* copy_tex_image_blit) = 0; + protected: GLES2Decoder(CommandBufferServiceBase* command_buffer_service, Outputter* outputter);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index 779687c..563e3ff 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -173,6 +173,9 @@ MOCK_METHOD1( SetCopyTextureResourceManagerForTest, void(CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager)); + MOCK_METHOD1( + SetCopyTexImageBlitterForTest, + void(CopyTexImageResourceManager* copy_texture_resource_manager)); private: base::WeakPtrFactory<MockGLES2Decoder> weak_ptr_factory_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc index 087f5877..90d923d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.cc
@@ -1697,6 +1697,11 @@ NOTIMPLEMENTED(); } +void GLES2DecoderPassthroughImpl::SetCopyTexImageBlitterForTest( + CopyTexImageResourceManager* copy_tex_image_blit) { + NOTIMPLEMENTED(); +} + const char* GLES2DecoderPassthroughImpl::GetCommandName( unsigned int command_id) const { if (command_id >= kFirstGLES2Command && command_id < kNumCommands) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index a987f08a..4a3fa61 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -360,6 +360,8 @@ void SetCopyTextureResourceManagerForTest( CopyTextureCHROMIUMResourceManager* copy_texture_resource_manager) override; + void SetCopyTexImageBlitterForTest( + CopyTexImageResourceManager* copy_tex_image_blit) override; void OnAbstractTextureDestroyed(PassthroughAbstractTextureImpl*, scoped_refptr<TexturePassthrough>);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index da702ff..c3ba97e7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -506,6 +506,11 @@ copy_texture_manager_ = new MockCopyTextureResourceManager(); decoder_->SetCopyTextureResourceManagerForTest(copy_texture_manager_); + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { + copy_tex_image_blitter_ = + new MockCopyTexImageResourceManager(feature_info.get()); + decoder_->SetCopyTexImageBlitterForTest(copy_tex_image_blitter_); + } ASSERT_EQ(decoder_->Initialize(surface_, context_, false, DisallowedFeatures(), attribs), @@ -1424,10 +1429,34 @@ EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, TexImage2D(target, level, internal_format, - width, height, border, format, type, _)) - .Times(1) - .RetiresOnSaturation(); + bool emulated_format = group_->feature_info()->gl_version_info().is_es3 && + (format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA || format == GL_ALPHA); + if (emulated_format) { + // The format of these textures may be different than requested due to + // emulation. + EXPECT_CALL(*gl_, + TexImage2D(target, level, _, width, height, border, _, type, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_R, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_G, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_B, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_A, _)) + .Times(1) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl_, TexImage2D(target, level, internal_format, width, height, + border, format, type, _)) + .Times(1) + .RetiresOnSaturation(); + } EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) .RetiresOnSaturation(); @@ -1546,6 +1575,25 @@ width, height)) .Times(1) .RetiresOnSaturation(); + } else if (group_->feature_info()->gl_version_info().is_es3) { + bool emulated = internal_format == GL_ALPHA || + internal_format == GL_LUMINANCE || + internal_format == GL_LUMINANCE_ALPHA; + if (emulated) { + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_R, _)) + .Times(testing::AtLeast(1)); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_G, _)) + .Times(testing::AtLeast(1)); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_B, _)) + .Times(testing::AtLeast(1)); + EXPECT_CALL(*gl_, TexParameteri(target, GL_TEXTURE_SWIZZLE_A, _)) + .Times(testing::AtLeast(1)); + } else { + EXPECT_CALL(*gl_, CopyTexImage2D(target, level, internal_format, 0, 0, + width, height, border)) + .Times(1) + .RetiresOnSaturation(); + } } else { EXPECT_CALL(*gl_, CopyTexImage2D(target, level, internal_format, 0, 0, width, height, border))
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 23a46460..9098e64 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -50,6 +50,7 @@ namespace gles2 { class MockCopyTextureResourceManager; +class MockCopyTexImageResourceManager; class GLES2DecoderTestBase : public ::testing::TestWithParam<bool>, public DecoderClient { @@ -816,7 +817,8 @@ MockGLStates gl_states_; base::MessageLoop message_loop_; - MockCopyTextureResourceManager* copy_texture_manager_; // not owned + MockCopyTextureResourceManager* copy_texture_manager_; // not owned + MockCopyTexImageResourceManager* copy_tex_image_blitter_; // not owned }; class GLES2DecoderWithShaderTestBase : public GLES2DecoderTestBase {
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 8f9d08c4..81d53d0a 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -1953,7 +1953,7 @@ } void Texture::ApplyFormatWorkarounds(FeatureInfo* feature_info) { - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) return; const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_]; @@ -3380,7 +3380,7 @@ const Texture::CompatibilitySwizzle* TextureManager::GetCompatibilitySwizzle( const gles2::FeatureInfo* feature_info, GLenum format) { - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { return GetCompatibilitySwizzleInternal(format); } else { return nullptr; @@ -3391,7 +3391,7 @@ GLenum TextureManager::AdjustTexInternalFormat( const gles2::FeatureInfo* feature_info, GLenum format) { - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { const Texture::CompatibilitySwizzle* swizzle = GetCompatibilitySwizzleInternal(format); if (swizzle) @@ -3411,7 +3411,7 @@ if (format == GL_SRGB_ALPHA_EXT) return GL_RGBA; } - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { const Texture::CompatibilitySwizzle* swizzle = GetCompatibilitySwizzleInternal(format); if (swizzle) @@ -3424,8 +3424,7 @@ GLenum TextureManager::AdjustTexStorageFormat( const gles2::FeatureInfo* feature_info, GLenum format) { - // We need to emulate luminance/alpha on core profile only. - if (feature_info->gl_version_info().is_desktop_core_profile) { + if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) { switch (format) { case GL_ALPHA8_EXT: return GL_R8_EXT;
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index ad123ab..9c18bcd 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -3063,6 +3063,11 @@ builders { mixins: "linux-try" mixins: "goma-j150" + name: "linux-coverage-rel" + } + builders { + mixins: "linux-try" + mixins: "goma-j150" name: "linux_chromium_rel_ng" } builders {
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index de53edb..ee8ad1c54 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -4891,6 +4891,9 @@ name: "buildbucket/luci.chromium.try/linux_chromium_component_updater" } builders { + name: "buildbucket/luci.chromium.try/linux-coverage-rel" + } + builders { name: "buildbucket/luci.chromium.try/linux_chromium_dbg_32_ng" } builders {
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index ef3f84ad..c394069 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -948,6 +948,9 @@ [_browserViewWrangler shutdown]; _browserViewWrangler = nil; + [_historyCoordinator stop]; + _historyCoordinator = nil; + [_mainCoordinator stop]; _httpProtocolHandlerDelegate.reset();
diff --git a/ios/chrome/browser/interstitials/ios_security_interstitial_page.h b/ios/chrome/browser/interstitials/ios_security_interstitial_page.h index 1a508e54..0f87f94 100644 --- a/ios/chrome/browser/interstitials/ios_security_interstitial_page.h +++ b/ios/chrome/browser/interstitials/ios_security_interstitial_page.h
@@ -21,7 +21,7 @@ class WebState; } -class IOSSecurityInterstitialPage : public web::HtmlWebInterstitialDelegate { +class IOSSecurityInterstitialPage : public web::WebInterstitialDelegate { public: IOSSecurityInterstitialPage(web::WebState* web_state, const GURL& request_url); @@ -42,7 +42,7 @@ // |web_interstitial_| will now have a value. virtual void AfterShow() = 0; - // web::HtmlWebInterstitialDelegate implementation. + // web::WebInterstitialDelegate implementation. std::string GetHtmlContents() const override; // Returns the formatted host name for the request url.
diff --git a/ios/chrome/browser/interstitials/ios_security_interstitial_page.mm b/ios/chrome/browser/interstitials/ios_security_interstitial_page.mm index f7dd88fc..f66ab07 100644 --- a/ios/chrome/browser/interstitials/ios_security_interstitial_page.mm +++ b/ios/chrome/browser/interstitials/ios_security_interstitial_page.mm
@@ -35,9 +35,9 @@ void IOSSecurityInterstitialPage::Show() { DCHECK(!web_interstitial_); - web_interstitial_ = web::WebInterstitial::CreateHtmlInterstitial( + web_interstitial_ = web::WebInterstitial::CreateInterstitial( web_state_, ShouldCreateNewNavigation(), request_url_, - std::unique_ptr<web::HtmlWebInterstitialDelegate>(this)); + std::unique_ptr<web::WebInterstitialDelegate>(this)); web_interstitial_->Show(); AfterShow(); }
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index eeebd7f4..b8a8cb9 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -420,7 +420,11 @@ _openInController = [[OpenInController alloc] initWithURLLoaderFactory:_browserState->GetSharedURLLoaderFactory() webController:self.webController]; - _openInController.baseView = self.view; + // If the tab was evicted before, It should have been loaded already before + // starting the open-in controller. + DCHECK(!self.webState->IsEvicted()); + self.webState->GetNavigationManager()->LoadIfNecessary(); + _openInController.baseView = self.webState->GetView(); } return _openInController; }
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm index c1a9eb7..67f6373a 100644 --- a/ios/chrome/browser/tabs/tab_unittest.mm +++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -200,6 +200,7 @@ OCMStub([mock_web_controller_ webViewNavigationProxy]) .andReturn(mock_web_view_); } + OCMStub([mock_web_controller_ isViewAlive]).andReturn(YES); web::WebState::CreateParams create_params(browser_state); web_state_impl_ = std::make_unique<web::WebStateImpl>(create_params);
diff --git a/ios/web/interstitials/BUILD.gn b/ios/web/interstitials/BUILD.gn index 5aba2499..2e38042 100644 --- a/ios/web/interstitials/BUILD.gn +++ b/ios/web/interstitials/BUILD.gn
@@ -15,10 +15,6 @@ ] sources = [ - "html_web_interstitial_impl.h", - "html_web_interstitial_impl.mm", - "native_web_interstitial_impl.h", - "native_web_interstitial_impl.mm", "web_interstitial_impl.h", "web_interstitial_impl.mm", ] @@ -45,6 +41,6 @@ ] sources = [ - "html_web_interstitial_unittest.mm", + "web_interstitial_unittest.mm", ] }
diff --git a/ios/web/interstitials/html_web_interstitial_impl.h b/ios/web/interstitials/html_web_interstitial_impl.h deleted file mode 100644 index 63b73a9..0000000 --- a/ios/web/interstitials/html_web_interstitial_impl.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2015 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_WEB_INTERSTITIALS_HTML_WEB_INTERSTITIAL_IMPL_H_ -#define IOS_WEB_INTERSTITIALS_HTML_WEB_INTERSTITIAL_IMPL_H_ - -#import <WebKit/WebKit.h> - -#include <memory> - -#import "ios/web/interstitials/web_interstitial_impl.h" - -namespace web { - -class HtmlWebInterstitialDelegate; -class HtmlWebInterstitialImpl; - -// A concrete subclass of WebInterstitialImpl that is used to display -// interstitials created via HTML. -class HtmlWebInterstitialImpl : public WebInterstitialImpl { - public: - HtmlWebInterstitialImpl( - WebStateImpl* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<HtmlWebInterstitialDelegate> delegate); - ~HtmlWebInterstitialImpl() override; - - // Called by |web_view_controller_delegate_| when |web_view_controller_| - // receives a JavaScript command. - void CommandReceivedFromWebView(NSString* command); - - // WebInterstitialImpl implementation: - CRWContentView* GetContentView() const override; - - protected: - // WebInterstitialImpl implementation: - void PrepareForDisplay() override; - WebInterstitialDelegate* GetDelegate() const override; - void ExecuteJavaScript(NSString* script, - JavaScriptResultBlock completion_handler) override; - - private: - // The HTML interstitial delegate. - std::unique_ptr<HtmlWebInterstitialDelegate> delegate_; - // The |web_view_|'s delegate. Used to forward JavaScript commands - // resulting from user interaction with the interstitial content. - id<WKNavigationDelegate> web_view_delegate_; - // The web view used to show the content. View needs to be resized by the - // caller. - WKWebView* web_view_; // strong - // The CRWContentView used to display |web_view_controller_|'s view. - CRWContentView* content_view_; -}; - -} // namespace web - -#endif // IOS_WEB_INTERSTITIALS_HTML_WEB_INTERSTITIAL_IMPL_H_
diff --git a/ios/web/interstitials/html_web_interstitial_impl.mm b/ios/web/interstitials/html_web_interstitial_impl.mm deleted file mode 100644 index e28d53d..0000000 --- a/ios/web/interstitials/html_web_interstitial_impl.mm +++ /dev/null
@@ -1,137 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/web/interstitials/html_web_interstitial_impl.h" - -#include <utility> - -#include "base/logging.h" -#include "base/strings/sys_string_conversions.h" -#import "ios/web/public/interstitials/web_interstitial_delegate.h" -#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" -#import "ios/web/public/web_view_creation_util.h" -#import "ios/web/web_state/ui/web_view_js_utils.h" -#import "ios/web/web_state/web_state_impl.h" -#import "net/base/mac/url_conversions.h" -#include "ui/gfx/geometry/size.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// The delegate of the web view that is used to display the HTML content. -// It intercepts JavaScript-triggered commands and forwards them -// to the interstitial. -@interface CRWWebInterstitialImplWKWebViewDelegate - : NSObject<WKNavigationDelegate> -// Initializes a CRWWebInterstitialImplWKWebViewDelegate which will -// forward JavaScript commands from its WKWebView to |interstitial|. -- (instancetype)initWithInterstitial: - (web::HtmlWebInterstitialImpl*)interstitial; -@end - -@implementation CRWWebInterstitialImplWKWebViewDelegate { - web::HtmlWebInterstitialImpl* _interstitial; -} - -- (instancetype)initWithInterstitial: - (web::HtmlWebInterstitialImpl*)interstitial { - self = [super init]; - if (self) - _interstitial = interstitial; - return self; -} - -- (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request { - NSString* requestString = [[request URL] absoluteString]; - // If the request is a JavaScript-triggered command, parse it and forward the - // command to |interstitial_|. - NSString* const commandPrefix = @"js-command:"; - if ([requestString hasPrefix:commandPrefix]) { - DCHECK(_interstitial); - _interstitial->CommandReceivedFromWebView( - [requestString substringFromIndex:commandPrefix.length]); - return NO; - } - return YES; -} - -#pragma mark - -#pragma mark WKNavigationDelegate methods - -- (void)webView:(WKWebView*)webView - decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction - decisionHandler: - (void (^)(WKNavigationActionPolicy))decisionHandler { - decisionHandler([self shouldStartLoadWithRequest:navigationAction.request] - ? WKNavigationActionPolicyAllow - : WKNavigationActionPolicyCancel); -} - -@end - -#pragma mark - - -namespace web { - -// static -WebInterstitial* WebInterstitial::CreateHtmlInterstitial( - WebState* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<HtmlWebInterstitialDelegate> delegate) { - WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state); - return new HtmlWebInterstitialImpl(web_state_impl, new_navigation, url, - std::move(delegate)); -} - -HtmlWebInterstitialImpl::HtmlWebInterstitialImpl( - WebStateImpl* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<HtmlWebInterstitialDelegate> delegate) - : WebInterstitialImpl(web_state, new_navigation, url), - delegate_(std::move(delegate)) { - DCHECK(delegate_); -} - -HtmlWebInterstitialImpl::~HtmlWebInterstitialImpl() { -} - -void HtmlWebInterstitialImpl::CommandReceivedFromWebView(NSString* command) { - delegate_->CommandReceived(base::SysNSStringToUTF8(command)); -} - -CRWContentView* HtmlWebInterstitialImpl::GetContentView() const { - return content_view_; -} - -void HtmlWebInterstitialImpl::PrepareForDisplay() { - if (!content_view_) { - web_view_delegate_ = [[CRWWebInterstitialImplWKWebViewDelegate alloc] - initWithInterstitial:this]; - web_view_ = - web::BuildWKWebView(CGRectZero, GetWebStateImpl()->GetBrowserState()); - [web_view_ setNavigationDelegate:web_view_delegate_]; - [web_view_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - NSString* html = base::SysUTF8ToNSString(delegate_->GetHtmlContents()); - [web_view_ loadHTMLString:html baseURL:net::NSURLWithGURL(GetUrl())]; - content_view_ = - [[CRWWebViewContentView alloc] initWithWebView:web_view_ - scrollView:[web_view_ scrollView]]; - } -} - -WebInterstitialDelegate* HtmlWebInterstitialImpl::GetDelegate() const { - return delegate_.get(); -} - -void HtmlWebInterstitialImpl::ExecuteJavaScript( - NSString* script, - JavaScriptResultBlock completion_handler) { - web::ExecuteJavaScript(web_view_, script, completion_handler); -} - -} // namespace web
diff --git a/ios/web/interstitials/native_web_interstitial_impl.h b/ios/web/interstitials/native_web_interstitial_impl.h deleted file mode 100644 index 3d62eca..0000000 --- a/ios/web/interstitials/native_web_interstitial_impl.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2015 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_WEB_INTERSTITIALS_NATIVE_WEB_INTERSTITIAL_IMPL_H_ -#define IOS_WEB_INTERSTITIALS_NATIVE_WEB_INTERSTITIAL_IMPL_H_ - -#import "ios/web/interstitials/web_interstitial_impl.h" - -#include <memory> - - -namespace web { - -class NativeWebInterstitialDelegate; - -// A concrete subclass of WebInterstitialImpl that is used to display -// interstitials created via native views. -class NativeWebInterstitialImpl : public WebInterstitialImpl { - public: - NativeWebInterstitialImpl( - WebStateImpl* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<NativeWebInterstitialDelegate> delegate); - ~NativeWebInterstitialImpl() override; - - // WebInterstitialImpl implementation: - CRWContentView* GetContentView() const override; - - protected: - // WebInterstitialImpl implementation: - void PrepareForDisplay() override; - WebInterstitialDelegate* GetDelegate() const override; - void ExecuteJavaScript(NSString* script, - JavaScriptResultBlock completion_handler) override; - - private: - // The native interstitial delegate. - std::unique_ptr<NativeWebInterstitialDelegate> delegate_; - // The transient content view containing interstitial content. - CRWContentView* content_view_; -}; - -} // namespace web - -#endif // IOS_WEB_INTERSTITIALS_NATIVE_WEB_INTERSTITIAL_IMPL_H_
diff --git a/ios/web/interstitials/native_web_interstitial_impl.mm b/ios/web/interstitials/native_web_interstitial_impl.mm deleted file mode 100644 index b78e268f..0000000 --- a/ios/web/interstitials/native_web_interstitial_impl.mm +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/web/interstitials/native_web_interstitial_impl.h" - -#include <utility> - -#include "base/logging.h" -#import "ios/web/public/interstitials/web_interstitial_delegate.h" -#import "ios/web/public/web_state/ui/crw_generic_content_view.h" -#import "ios/web/web_state/web_state_impl.h" -#include "ui/gfx/geometry/size.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace web { - -// static -WebInterstitial* WebInterstitial::CreateNativeInterstitial( - WebState* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<NativeWebInterstitialDelegate> delegate) { - WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state); - return new NativeWebInterstitialImpl(web_state_impl, new_navigation, url, - std::move(delegate)); -} - -NativeWebInterstitialImpl::NativeWebInterstitialImpl( - WebStateImpl* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<NativeWebInterstitialDelegate> delegate) - : web::WebInterstitialImpl(web_state, new_navigation, url), - delegate_(std::move(delegate)) { - DCHECK(delegate_); -} - -NativeWebInterstitialImpl::~NativeWebInterstitialImpl() { -} - -CRWContentView* NativeWebInterstitialImpl::GetContentView() const { - return content_view_; -} - -void NativeWebInterstitialImpl::PrepareForDisplay() { - if (!content_view_) { - content_view_ = [[CRWGenericContentView alloc] - initWithView:delegate_->GetContentView()]; - } -} - -WebInterstitialDelegate* NativeWebInterstitialImpl::GetDelegate() const { - return delegate_.get(); -} - -void NativeWebInterstitialImpl::ExecuteJavaScript( - NSString* script, - JavaScriptResultBlock completion_handler) { - NOTREACHED() << "JavaScript cannot be executed on native interstitials."; -} - -} // namespace web
diff --git a/ios/web/interstitials/web_interstitial_impl.h b/ios/web/interstitials/web_interstitial_impl.h index 6ce6e336..ec8959aa 100644 --- a/ios/web/interstitials/web_interstitial_impl.h +++ b/ios/web/interstitials/web_interstitial_impl.h
@@ -13,6 +13,9 @@ #import "ios/web/web_state/ui/web_view_js_utils.h" #include "url/gurl.h" +@protocol WKNavigationDelegate; +@class WKWebView; + namespace web { class NavigationManagerImpl; @@ -32,11 +35,12 @@ public: WebInterstitialImpl(WebStateImpl* web_state, bool new_navigation, - const GURL& url); + const GURL& url, + std::unique_ptr<WebInterstitialDelegate> delegate); ~WebInterstitialImpl() override; // Returns the transient content view used to display interstitial content. - virtual CRWContentView* GetContentView() const = 0; + virtual CRWContentView* GetContentView() const; // Returns the url corresponding to this interstitial. const GURL& GetUrl() const; @@ -50,23 +54,16 @@ // WebStateObserver implementation: void WebStateDestroyed(WebState* web_state) override; - protected: - // Called before the WebInterstitialImpl is shown, giving subclasses a chance - // to instantiate its view. - virtual void PrepareForDisplay() {} - - // Returns the WebInterstitialDelegate that will handle Proceed/DontProceed - // user actions. - virtual WebInterstitialDelegate* GetDelegate() const = 0; - - // Convenience method for getting the WebStateImpl. - WebStateImpl* GetWebStateImpl() const; + // Called by |web_view_controller_delegate_| when |web_view_controller_| + // receives a JavaScript command. This method forwards the command to + // WebInterstitialDelegate::CommandReceived. + void CommandReceivedFromWebView(NSString* command); // Executes the given |script| on interstitial's web view if there is one. // Calls |completionHandler| with results of the evaluation. // The |completionHandler| can be nil. Must be used only for testing. virtual void ExecuteJavaScript(NSString* script, - JavaScriptResultBlock completion_handler) = 0; + JavaScriptResultBlock completion_handler); private: // The WebState this instance is observing. Will be null after @@ -83,6 +80,16 @@ // Whether or not either Proceed() or DontProceed() has been called. bool action_taken_; + std::unique_ptr<WebInterstitialDelegate> delegate_; + // The |web_view_|'s delegate. Used to forward JavaScript commands + // resulting from user interaction with the interstitial content. + id<WKNavigationDelegate> web_view_delegate_; + // The web view used to show the content. View needs to be resized by the + // caller. + WKWebView* web_view_; + // View that encapsulates interstitial's web view and scroll view. + CRWContentView* content_view_; + // Must be implemented only for testing purposes. friend void web::ExecuteScriptForTesting(WebInterstitialImpl*, NSString*,
diff --git a/ios/web/interstitials/web_interstitial_impl.mm b/ios/web/interstitials/web_interstitial_impl.mm index 728ab612..02bb0ce 100644 --- a/ios/web/interstitials/web_interstitial_impl.mm +++ b/ios/web/interstitials/web_interstitial_impl.mm
@@ -4,28 +4,97 @@ #import "ios/web/interstitials/web_interstitial_impl.h" +#import <WebKit/WebKit.h> + #include "base/logging.h" +#include "base/strings/sys_string_conversions.h" #import "ios/web/navigation/navigation_manager_impl.h" #import "ios/web/public/interstitials/web_interstitial_delegate.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/reload_type.h" +#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" +#import "ios/web/public/web_view_creation_util.h" #import "ios/web/web_state/web_state_impl.h" +#import "net/base/mac/url_conversions.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +// The delegate of the web view that is used to display the HTML content. +// It intercepts JavaScript-triggered commands and forwards them +// to the interstitial. +@interface CRWWebInterstitialImplWKWebViewDelegate + : NSObject<WKNavigationDelegate> +// Initializes a CRWWebInterstitialImplWKWebViewDelegate which will +// forward JavaScript commands from its WKWebView to |interstitial|. +- (instancetype)initWithInterstitial:(web::WebInterstitialImpl*)interstitial; +@end + +@implementation CRWWebInterstitialImplWKWebViewDelegate { + web::WebInterstitialImpl* _interstitial; +} + +- (instancetype)initWithInterstitial:(web::WebInterstitialImpl*)interstitial { + self = [super init]; + if (self) + _interstitial = interstitial; + return self; +} + +- (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request { + NSString* requestString = request.URL.absoluteString; + // If the request is a JavaScript-triggered command, parse it and forward the + // command to |interstitial_|. + NSString* const kCommandPrefix = @"js-command:"; + if ([requestString hasPrefix:kCommandPrefix]) { + DCHECK(_interstitial); + _interstitial->CommandReceivedFromWebView( + [requestString substringFromIndex:kCommandPrefix.length]); + return NO; + } + return YES; +} + +#pragma mark - +#pragma mark WKNavigationDelegate methods + +- (void)webView:(WKWebView*)webView + decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction + decisionHandler: + (void (^)(WKNavigationActionPolicy))decisionHandler { + decisionHandler([self shouldStartLoadWithRequest:navigationAction.request] + ? WKNavigationActionPolicyAllow + : WKNavigationActionPolicyCancel); +} + +@end + namespace web { -WebInterstitialImpl::WebInterstitialImpl(WebStateImpl* web_state, - bool new_navigation, - const GURL& url) +// static +WebInterstitial* WebInterstitial::CreateInterstitial( + WebState* web_state, + bool new_navigation, + const GURL& url, + std::unique_ptr<WebInterstitialDelegate> delegate) { + WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state); + return new WebInterstitialImpl(web_state_impl, new_navigation, url, + std::move(delegate)); +} + +WebInterstitialImpl::WebInterstitialImpl( + WebStateImpl* web_state, + bool new_navigation, + const GURL& url, + std::unique_ptr<WebInterstitialDelegate> delegate) : web_state_(web_state), navigation_manager_(&web_state->GetNavigationManagerImpl()), url_(url), new_navigation_(new_navigation), - action_taken_(false) { - DCHECK(web_state_); + action_taken_(false), + delegate_(std::move(delegate)) { + DCHECK(delegate_); web_state_->AddObserver(this); } @@ -37,13 +106,30 @@ } } +CRWContentView* WebInterstitialImpl::GetContentView() const { + return content_view_; +} + const GURL& WebInterstitialImpl::GetUrl() const { return url_; } void WebInterstitialImpl::Show() { - PrepareForDisplay(); - GetWebStateImpl()->ShowWebInterstitial(this); + if (!content_view_) { + web_view_delegate_ = [[CRWWebInterstitialImplWKWebViewDelegate alloc] + initWithInterstitial:this]; + web_view_ = web::BuildWKWebView(CGRectZero, web_state_->GetBrowserState()); + [web_view_ setNavigationDelegate:web_view_delegate_]; + [web_view_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight)]; + NSString* html = base::SysUTF8ToNSString(delegate_->GetHtmlContents()); + [web_view_ loadHTMLString:html baseURL:net::NSURLWithGURL(GetUrl())]; + content_view_ = + [[CRWWebViewContentView alloc] initWithWebView:web_view_ + scrollView:[web_view_ scrollView]]; + } + + web_state_->ShowWebInterstitial(this); if (new_navigation_) { // TODO(crbug.com/706578): Plumb transient entry handling through @@ -51,14 +137,14 @@ navigation_manager_->AddTransientItem(url_); // Give delegates a chance to set some states on the navigation item. - GetDelegate()->OverrideItem(navigation_manager_->GetTransientItem()); + delegate_->OverrideItem(navigation_manager_->GetTransientItem()); web_state_->DidChangeVisibleSecurityState(); } } void WebInterstitialImpl::Hide() { - GetWebStateImpl()->ClearTransientContent(); + web_state_->ClearTransientContent(); } void WebInterstitialImpl::DontProceed() { @@ -69,11 +155,11 @@ // Clear the pending entry, since that's the page that's not being // proceeded to. - GetWebStateImpl()->GetNavigationManager()->DiscardNonCommittedItems(); + web_state_->GetNavigationManager()->DiscardNonCommittedItems(); Hide(); - GetDelegate()->OnDontProceed(); + delegate_->OnDontProceed(); delete this; } @@ -84,7 +170,7 @@ return; action_taken_ = true; Hide(); - GetDelegate()->OnProceed(); + delegate_->OnProceed(); delete this; } @@ -97,8 +183,14 @@ DontProceed(); } -WebStateImpl* WebInterstitialImpl::GetWebStateImpl() const { - return web_state_; +void WebInterstitialImpl::CommandReceivedFromWebView(NSString* command) { + delegate_->CommandReceived(base::SysNSStringToUTF8(command)); +} + +void WebInterstitialImpl::ExecuteJavaScript( + NSString* script, + JavaScriptResultBlock completion_handler) { + web::ExecuteJavaScript(web_view_, script, completion_handler); } } // namespace web
diff --git a/ios/web/interstitials/html_web_interstitial_unittest.mm b/ios/web/interstitials/web_interstitial_unittest.mm similarity index 84% rename from ios/web/interstitials/html_web_interstitial_unittest.mm rename to ios/web/interstitials/web_interstitial_unittest.mm index 6730f57..367e67f 100644 --- a/ios/web/interstitials/html_web_interstitial_unittest.mm +++ b/ios/web/interstitials/web_interstitial_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/interstitials/html_web_interstitial_impl.h" +#import "ios/web/public/interstitials/web_interstitial.h" #include <memory> @@ -25,8 +25,8 @@ } // namespace -// Test fixture for HtmlWebInterstitialImpl class. -class HtmlWebInterstitialImplTest : public WebTest { +// Test fixture for WebInterstitial class. +class WebInterstitialTest : public WebTest { protected: void SetUp() override { WebTest::SetUp(); @@ -46,7 +46,7 @@ }; // Tests that the interstitial is shown and dismissed on Proceed call. -TEST_F(HtmlWebInterstitialImplTest, Proceed) { +TEST_F(WebInterstitialTest, Proceed) { ASSERT_FALSE(web_state_->IsShowingWebInterstitial()); GURL url(kTestHostName); @@ -55,7 +55,7 @@ EXPECT_CALL(*delegate.get(), OnProceed()); // Raw pointer to |interstitial| because it deletes itself when dismissed. - HtmlWebInterstitialImpl* interstitial = new HtmlWebInterstitialImpl( + WebInterstitial* interstitial = WebInterstitial::CreateInterstitial( web_state_.get(), true, url, std::move(delegate)); interstitial->Show(); ASSERT_TRUE(web_state_->IsShowingWebInterstitial()); @@ -65,7 +65,7 @@ } // Tests that the interstitial is shown and dismissed on DontProceed call. -TEST_F(HtmlWebInterstitialImplTest, DontProceed) { +TEST_F(WebInterstitialTest, DontProceed) { ASSERT_FALSE(web_state_->IsShowingWebInterstitial()); std::unique_ptr<MockInterstitialDelegate> delegate = @@ -73,7 +73,7 @@ EXPECT_CALL(*delegate.get(), OnDontProceed()); // Raw pointer to |interstitial| because it deletes itself when dismissed. - HtmlWebInterstitialImpl* interstitial = new HtmlWebInterstitialImpl( + WebInterstitial* interstitial = WebInterstitial::CreateInterstitial( web_state_.get(), true, GURL(kTestHostName), std::move(delegate)); interstitial->Show(); ASSERT_TRUE(web_state_->IsShowingWebInterstitial()); @@ -83,13 +83,13 @@ } // Tests that presenting an interstitial changes the visible security state. -TEST_F(HtmlWebInterstitialImplTest, VisibleSecurityStateChanged) { +TEST_F(WebInterstitialTest, VisibleSecurityStateChanged) { TestWebStateObserver observer(web_state_.get()); std::unique_ptr<MockInterstitialDelegate> delegate = std::make_unique<MockInterstitialDelegate>(); // Raw pointer to |interstitial| because it deletes itself when dismissed. - HtmlWebInterstitialImpl* interstitial = new HtmlWebInterstitialImpl( + WebInterstitial* interstitial = WebInterstitial::CreateInterstitial( web_state_.get(), true, GURL(kTestHostName), std::move(delegate)); interstitial->Show(); @@ -100,14 +100,14 @@ } // Tests that the interstitial is dismissed when the web state is destroyed. -TEST_F(HtmlWebInterstitialImplTest, WebStateDestroyed) { +TEST_F(WebInterstitialTest, WebStateDestroyed) { std::unique_ptr<MockInterstitialDelegate> delegate = std::make_unique<MockInterstitialDelegate>(); // Interstitial should be dismissed if web state is destroyed. EXPECT_CALL(*delegate.get(), OnDontProceed()); // Raw pointer to |interstitial| because it deletes itself when dismissed. - HtmlWebInterstitialImpl* interstitial = new HtmlWebInterstitialImpl( + WebInterstitial* interstitial = WebInterstitial::CreateInterstitial( web_state_.get(), true, GURL(kTestHostName), std::move(delegate)); interstitial->Show();
diff --git a/ios/web/public/interstitials/web_interstitial.h b/ios/web/public/interstitials/web_interstitial.h index c9130fb..399ee4a 100644 --- a/ios/web/public/interstitials/web_interstitial.h +++ b/ios/web/public/interstitials/web_interstitial.h
@@ -11,8 +11,7 @@ namespace web { -class HtmlWebInterstitialDelegate; -class NativeWebInterstitialDelegate; +class WebInterstitialDelegate; class WebState; // This class is used for showing interstitial pages, pages that show some @@ -28,16 +27,11 @@ // |delegate|. Reloading the interstitial page will result in a new navigation // to |url|. The pointers returned by these functions are self-owning; they // manage their own deletion after calling |Show()|. - static WebInterstitial* CreateHtmlInterstitial( + static WebInterstitial* CreateInterstitial( WebState* web_state, bool new_navigation, const GURL& url, - std::unique_ptr<HtmlWebInterstitialDelegate> delegate); - static WebInterstitial* CreateNativeInterstitial( - WebState* web_state, - bool new_navigation, - const GURL& url, - std::unique_ptr<NativeWebInterstitialDelegate> delegate); + std::unique_ptr<WebInterstitialDelegate> delegate); virtual ~WebInterstitial() {}
diff --git a/ios/web/public/interstitials/web_interstitial_delegate.h b/ios/web/public/interstitials/web_interstitial_delegate.h index 6b6c3e02..128a7f1 100644 --- a/ios/web/public/interstitials/web_interstitial_delegate.h +++ b/ios/web/public/interstitials/web_interstitial_delegate.h
@@ -32,11 +32,7 @@ // Note that this is only called if the WebInterstitial was constructed with // |new_navigation| set to true. virtual void OverrideItem(NavigationItem* item) {} -}; -// Provides HTML to an HTMLWebInterstitialImpl. -class HtmlWebInterstitialDelegate : public WebInterstitialDelegate { - public: // Returns the HTML that should be displayed in the page. virtual std::string GetHtmlContents() const = 0; @@ -44,16 +40,6 @@ virtual void CommandReceived(const std::string& command) {} }; -// Provides a native content view to NativeWebInterstitialImpls. -class NativeWebInterstitialDelegate : public WebInterstitialDelegate { - public: - // Returns the content view for native interstitials. - virtual UIView* GetContentView() = 0; - - // The desired background color for the interstitial's scroll view. - virtual UIColor* GetScrollViewBackgroundColor() const = 0; -}; - } // namespace web #endif // IOS_WEB_PUBLIC_INTERSTITIALS_WEB_INTERSTITIAL_DELEGATE_H_
diff --git a/ios/web/test/fakes/mock_interstitial_delegate.h b/ios/web/test/fakes/mock_interstitial_delegate.h index c9708ab3..8619ffe 100644 --- a/ios/web/test/fakes/mock_interstitial_delegate.h +++ b/ios/web/test/fakes/mock_interstitial_delegate.h
@@ -9,7 +9,7 @@ #include "testing/gmock/include/gmock/gmock.h" // A mock html web interstitial delegate. -class MockInterstitialDelegate : public web::HtmlWebInterstitialDelegate { +class MockInterstitialDelegate : public web::WebInterstitialDelegate { public: MockInterstitialDelegate(); ~MockInterstitialDelegate();
diff --git a/ios/web/web_state/web_state_impl_unittest.mm b/ios/web/web_state/web_state_impl_unittest.mm index 3b657aa..9d46a9e4 100644 --- a/ios/web/web_state/web_state_impl_unittest.mm +++ b/ios/web/web_state/web_state_impl_unittest.mm
@@ -16,7 +16,7 @@ #import "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #include "base/test/scoped_feature_list.h" -#import "ios/web/interstitials/html_web_interstitial_impl.h" +#import "ios/web/interstitials/web_interstitial_impl.h" #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/wk_navigation_util.h" #import "ios/web/public/crw_navigation_item_storage.h" @@ -233,8 +233,8 @@ WebInterstitialImpl* ShowInterstitial() { auto delegate = std::make_unique<MockInterstitialDelegate>(); WebInterstitialImpl* result = - new HtmlWebInterstitialImpl(web_state_.get(), /*new_navigation=*/true, - GURL::EmptyGURL(), std::move(delegate)); + new WebInterstitialImpl(web_state_.get(), /*new_navigation=*/true, + GURL::EmptyGURL(), std::move(delegate)); result->Show(); return result; }
diff --git a/media/learning/BUILD.gn b/media/learning/BUILD.gn index 2300291..a0896b7 100644 --- a/media/learning/BUILD.gn +++ b/media/learning/BUILD.gn
@@ -2,40 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("learning") { - # Do not expand the visibility here without double-checking with OWNERS, this - # is a roll-up target which is part of the //media component. Most other DEPs - # should be using //media and not directly DEP this roll-up target. - visibility = [ "//media" ] - - sources = [ - "instance.cc", - "instance.h", - "learner.h", - "learner_factory.h", - "learning_task.cc", - "learning_task.h", - "value.cc", - "value.h", - ] - - public_deps = [ - "//base", - "//media/base", - ] - - configs += [ "//media:subcomponent_config" ] -} - source_set("unit_tests") { testonly = true - sources = [ - "value_unittest.cc", - ] deps = [ "//base/test:test_support", "//media:test_support", + "//media/learning/common:unit_tests", "//testing/gtest", ] }
diff --git a/media/learning/README.md b/media/learning/README.md index 6a87dc43..a88b279 100644 --- a/media/learning/README.md +++ b/media/learning/README.md
@@ -64,3 +64,8 @@ ## Models All of our models are supervised. + +## Directory Structure + + * `common/` - public interfaces + * `impl/` - learning algorithms, other implementation details
diff --git a/media/learning/common/BUILD.gn b/media/learning/common/BUILD.gn new file mode 100644 index 0000000..1b4e43d --- /dev/null +++ b/media/learning/common/BUILD.gn
@@ -0,0 +1,44 @@ +# Copyright 2018 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. + +component("common") { + output_name = "learning_common" + visibility = [ + "//media/learning", + "//media/learning/impl:*", + "//media/learning/impl:test_support", + "//media/learning/common:unit_tests", + ] + + defines = [ "IS_LEARNING_COMMON_IMPL" ] + + sources = [ + "instance.cc", + "instance.h", + "learning_session.cc", + "learning_session.h", + "learning_task.cc", + "learning_task.h", + "value.cc", + "value.h", + ] + + deps = [ + "//base", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "value_unittest.cc", + ] + + deps = [ + ":common", + "//base/test:test_support", + "//media:test_support", + "//testing/gtest", + ] +}
diff --git a/media/learning/instance.cc b/media/learning/common/instance.cc similarity index 67% rename from media/learning/instance.cc rename to media/learning/common/instance.cc index eb0c1a0..ee7d0d5c 100644 --- a/media/learning/instance.cc +++ b/media/learning/common/instance.cc
@@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/learning/instance.h" +#include "media/learning/common/instance.h" namespace media { namespace learning { Instance::Instance() = default; + +Instance::Instance(std::initializer_list<FeatureValue> init_list) + : features(init_list) {} + Instance::~Instance() = default; -Instance::Instance(Instance&& rhs) noexcept { - features = std::move(rhs.features); -} std::ostream& operator<<(std::ostream& out, const Instance& instance) { for (const auto& feature : instance.features) @@ -20,5 +21,9 @@ return out; } +bool Instance::operator==(const Instance& rhs) const { + return features == rhs.features; +} + } // namespace learning } // namespace media
diff --git a/media/learning/common/instance.h b/media/learning/common/instance.h new file mode 100644 index 0000000..d0e4a6f --- /dev/null +++ b/media/learning/common/instance.h
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_COMMON_INSTANCE_H_ +#define MEDIA_LEARNING_COMMON_INSTANCE_H_ + +#include <initializer_list> +#include <ostream> +#include <vector> + +#include "base/component_export.h" +#include "base/macros.h" +#include "media/learning/common/value.h" + +namespace media { +namespace learning { + +// One instance == group of feature values. +struct COMPONENT_EXPORT(LEARNING_COMMON) Instance { + Instance(); + Instance(std::initializer_list<FeatureValue> init_list); + ~Instance(); + + bool operator==(const Instance& rhs) const; + + // It's up to you to add the right number of features to match the learner + // description. Otherwise, the learner will ignore (training) or lie to you + // (inference), silently. + std::vector<FeatureValue> features; + + // Copy / assignment is allowed. +}; + +COMPONENT_EXPORT(LEARNING_COMMON) +std::ostream& operator<<(std::ostream& out, const Instance& instance); + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_COMMON_INSTANCE_H_
diff --git a/media/learning/common/learning_session.cc b/media/learning/common/learning_session.cc new file mode 100644 index 0000000..e54d57e --- /dev/null +++ b/media/learning/common/learning_session.cc
@@ -0,0 +1,15 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/common/learning_session.h" + +namespace media { +namespace learning { + +LearningSession::LearningSession() = default; + +LearningSession::~LearningSession() = default; + +} // namespace learning +} // namespace media
diff --git a/media/learning/common/learning_session.h b/media/learning/common/learning_session.h new file mode 100644 index 0000000..d90c075 --- /dev/null +++ b/media/learning/common/learning_session.h
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_COMMON_LEARNING_SESSION_H_ +#define MEDIA_LEARNING_COMMON_LEARNING_SESSION_H_ + +#include <string> + +#include "base/component_export.h" +#include "base/macros.h" +#include "media/learning/common/learning_task.h" + +namespace media { +namespace learning { + +// Interface to provide a Learner given the task name. +class COMPONENT_EXPORT(LEARNING_COMMON) LearningSession { + public: + LearningSession(); + virtual ~LearningSession(); + + // Add an observed example of |instance| with target value |target| to the + // learning task |task_name|. + // TODO(liberato): Consider making this an enum to match mojo. + virtual void AddExample(const std::string& task_name, + const Instance& instance, + const TargetValue& target) = 0; + + // TODO(liberato): Add prediction API. + + private: + DISALLOW_COPY_AND_ASSIGN(LearningSession); +}; + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_COMMON_LEARNING_SESSION_H_
diff --git a/media/learning/learning_task.cc b/media/learning/common/learning_task.cc similarity index 88% rename from media/learning/learning_task.cc rename to media/learning/common/learning_task.cc index 78e43d23..acc339b 100644 --- a/media/learning/learning_task.cc +++ b/media/learning/common/learning_task.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/learning/learning_task.h" +#include "media/learning/common/learning_task.h" namespace media { namespace learning {
diff --git a/media/learning/learning_task.h b/media/learning/common/learning_task.h similarity index 88% rename from media/learning/learning_task.h rename to media/learning/common/learning_task.h index 2fe086c..378dbb13 100644 --- a/media/learning/learning_task.h +++ b/media/learning/common/learning_task.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_LEARNING_LEARNING_TASK_H_ -#define MEDIA_LEARNING_LEARNING_TASK_H_ +#ifndef MEDIA_LEARNING_COMMON_LEARNING_TASK_H_ +#define MEDIA_LEARNING_COMMON_LEARNING_TASK_H_ #include <initializer_list> #include <string> -#include "media/base/media_export.h" -#include "media/learning/instance.h" +#include "base/component_export.h" +#include "media/learning/common/instance.h" namespace media { namespace learning { @@ -18,7 +18,9 @@ // inputs (features) and output (target value), plus a choice of the model and // parameters for learning. // TODO(liberato): Consider separating the task from the choice of model. -struct MEDIA_EXPORT LearningTask { +// TODO(liberato): should this be in impl? Probably not if we want to allow +// registering tasks. +struct COMPONENT_EXPORT(LEARNING_COMMON) LearningTask { // Not all models support all feature / target descriptions. For example, // NaiveBayes requires kUnordered features. Similarly, kLogLinear doesn't // support kUnordered features or targets. kRandomForest might support more @@ -93,4 +95,4 @@ } // namespace learning } // namespace media -#endif // MEDIA_LEARNING_LEARNING_TASK_H_ +#endif // MEDIA_LEARNING_COMMON_LEARNING_TASK_H_
diff --git a/media/learning/value.cc b/media/learning/common/value.cc similarity index 93% rename from media/learning/value.cc rename to media/learning/common/value.cc index 88e1033..ff80a847 100644 --- a/media/learning/value.cc +++ b/media/learning/common/value.cc
@@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/learning/value.h" +#include "media/learning/common/value.h" #include "base/hash.h" namespace media { namespace learning { +Value::Value() = default; + Value::Value(int x) : value_(x) {} + Value::Value(const char* x) { // std::hash would be nice, but it can (and does) change values between // different instances of the class. In other words, Value("foo") !=
diff --git a/media/learning/value.h b/media/learning/common/value.h similarity index 70% rename from media/learning/value.h rename to media/learning/common/value.h index fc49f47..c468deb2 100644 --- a/media/learning/value.h +++ b/media/learning/common/value.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_LEARNING_VALUE_H_ -#define MEDIA_LEARNING_VALUE_H_ +#ifndef MEDIA_LEARNING_COMMON_VALUE_H_ +#define MEDIA_LEARNING_COMMON_VALUE_H_ #include <cstdint> #include <ostream> #include <string> -#include "media/base/media_export.h" +#include "base/component_export.h" namespace media { namespace learning { @@ -22,8 +22,9 @@ // For numeric values, ==, !=, > operators behave as one would expect. // // For strings, only == and != are guaranteed to be meaningful. -class MEDIA_EXPORT Value { +class COMPONENT_EXPORT(LEARNING_COMMON) Value { public: + Value(); explicit Value(int x); explicit Value(const char* x); explicit Value(const std::string& x); @@ -34,11 +35,14 @@ bool operator!=(const Value& rhs) const; bool operator<(const Value& rhs) const; + int64_t value() const { return value_; } + private: int64_t value_ = 0; - friend MEDIA_EXPORT std::ostream& operator<<(std::ostream& out, - const Value& value); + friend COMPONENT_EXPORT(LEARNING_COMMON) std::ostream& operator<<( + std::ostream& out, + const Value& value); // Copy and assign are fine. }; @@ -47,9 +51,10 @@ using FeatureValue = Value; using TargetValue = Value; -MEDIA_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value); +COMPONENT_EXPORT(LEARNING_COMMON) +std::ostream& operator<<(std::ostream& out, const Value& value); } // namespace learning } // namespace media -#endif // MEDIA_LEARNING_VALUE_H_ +#endif // MEDIA_LEARNING_COMMON_VALUE_H_
diff --git a/media/learning/value_unittest.cc b/media/learning/common/value_unittest.cc similarity index 96% rename from media/learning/value_unittest.cc rename to media/learning/common/value_unittest.cc index 054d419c..f4c9e0a 100644 --- a/media/learning/value_unittest.cc +++ b/media/learning/common/value_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/learning/value.h" +#include "media/learning/common/value.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/learning/impl/BUILD.gn b/media/learning/impl/BUILD.gn new file mode 100644 index 0000000..427bce5d2 --- /dev/null +++ b/media/learning/impl/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2018 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. + +component("impl") { + output_name = "learning_impl" + sources = [ + "learner.h", + "learning_session_impl.cc", + "learning_session_impl.h", + ] + + defines = [ "IS_LEARNING_IMPL_IMPL" ] + + deps = [ + "//base", + ] + + public_deps = [ + "//media/learning/common", + ] +}
diff --git a/media/learning/learner.h b/media/learning/impl/learner.h similarity index 77% rename from media/learning/learner.h rename to media/learning/impl/learner.h index bff1cbb..b8564b20 100644 --- a/media/learning/learner.h +++ b/media/learning/impl/learner.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_LEARNING_LEARNER_H_ -#define MEDIA_LEARNING_LEARNER_H_ +#ifndef MEDIA_LEARNING_IMPL_LEARNER_H_ +#define MEDIA_LEARNING_IMPL_LEARNER_H_ +#include "base/component_export.h" #include "base/values.h" -#include "media/base/media_export.h" -#include "media/learning/instance.h" +#include "media/learning/common/instance.h" namespace media { namespace learning { @@ -16,7 +16,7 @@ // and trains a model to predict the target given the features. The target may // be either nominal (classification) or numeric (regression), though this must // be chosen in advance when creating the learner via LearnerFactory. -class MEDIA_EXPORT Learner { +class COMPONENT_EXPORT(LEARNING_IMPL) Learner { public: virtual ~Learner() = default; @@ -29,4 +29,4 @@ } // namespace learning } // namespace media -#endif // MEDIA_LEARNING_LEARNER_H_ +#endif // MEDIA_LEARNING_IMPL_LEARNER_H_
diff --git a/media/learning/impl/learning_session_impl.cc b/media/learning/impl/learning_session_impl.cc new file mode 100644 index 0000000..5d0166f --- /dev/null +++ b/media/learning/impl/learning_session_impl.cc
@@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/learning_session_impl.h" + +#include "base/logging.h" + +namespace media { +namespace learning { + +LearningSessionImpl::LearningSessionImpl() = default; +LearningSessionImpl::~LearningSessionImpl() = default; + +void LearningSessionImpl::AddExample(const std::string& task_name, + const Instance& instance, + const TargetValue& target) { + // TODO: match |task_name| against a list of learning tasks, and find the + // learner(s) for it. Then add |instance|, |target| to it. + NOTIMPLEMENTED(); +} + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/learning_session_impl.h b/media/learning/impl/learning_session_impl.h new file mode 100644 index 0000000..bf0f5a8c --- /dev/null +++ b/media/learning/impl/learning_session_impl.h
@@ -0,0 +1,31 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_IMPL_LEARNING_SESSION_IMPL_H_ +#define MEDIA_LEARNING_IMPL_LEARNING_SESSION_IMPL_H_ + +#include "base/component_export.h" +#include "media/learning/common/learning_session.h" + +namespace media { +namespace learning { + +// Concrete implementation of a LearningSession. This would have a list of +// learning tasks, and could provide local learners for each task. +class COMPONENT_EXPORT(LEARNING_IMPL) LearningSessionImpl + : public LearningSession { + public: + LearningSessionImpl(); + ~LearningSessionImpl() override; + + // LearningSession + void AddExample(const std::string& task_name, + const Instance& instance, + const TargetValue& target) override; +}; + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_IMPL_LEARNING_SESSION_IMPL_H_
diff --git a/media/learning/instance.h b/media/learning/instance.h deleted file mode 100644 index 2a30770..0000000 --- a/media/learning/instance.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_LEARNING_INSTANCE_H_ -#define MEDIA_LEARNING_INSTANCE_H_ - -#include <ostream> -#include <vector> - -#include "base/macros.h" -#include "media/base/media_export.h" -#include "media/learning/value.h" - -namespace media { -namespace learning { - -// One instance == group of feature values. -struct MEDIA_EXPORT Instance { - Instance(); - ~Instance(); - // Declare a no-exception move constructor so that std::vector will use it. - Instance(Instance&& rhs) noexcept; - - // It's up to you to add the right number of features to match the learner - // description. Otherwise, the learner will ignore (training) or lie to you - // (inference), silently. - std::vector<FeatureValue> features; - - DISALLOW_COPY_AND_ASSIGN(Instance); -}; - -MEDIA_EXPORT std::ostream& operator<<(std::ostream& out, - const Instance& instance); - -} // namespace learning -} // namespace media - -#endif // MEDIA_LEARNING_INSTANCE_H_
diff --git a/media/learning/learner_factory.h b/media/learning/learner_factory.h deleted file mode 100644 index fc30f31f..0000000 --- a/media/learning/learner_factory.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_LEARNING_LEARNER_FACTORY_H_ -#define MEDIA_LEARNING_LEARNER_FACTORY_H_ - -#include <string> - -#include "media/base/media_export.h" -#include "media/learning/learing_task.h" -#include "media/learning/learner.h" - -namespace media { -namespace learning { - -// Factory class for learner instances. -class MEDIA_EXPORT LearnerFactory { - public: - virtual ~LearnerFactory() = default; - - // Provide a learner that matches |task|. - virtual std::unique_ptr<Learner> CreateLearner(const LearningTask& task) = 0; -}; - -} // namespace learning -} // namespace media - -#endif // MEDIA_LEARNING_LEARNER_FACTORY_H_
diff --git a/media/media_options.gni b/media/media_options.gni index fed7f8c..46eaa581 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -21,7 +21,6 @@ "//media/device_monitors", "//media/filters", "//media/formats", - "//media/learning", "//media/muxers", "//media/renderers", "//media/video",
diff --git a/media/mojo/DEPS b/media/mojo/DEPS index 496a6c52..258ba11 100644 --- a/media/mojo/DEPS +++ b/media/mojo/DEPS
@@ -1,7 +1,5 @@ include_rules = [ "+components/ukm/test_ukm_recorder.h", - "+mojo/converters", - "+mojo/logging", "+mojo/public", # For changing the bad message handler for tests.
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index 6579bb0..ba3eccfc 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -32,6 +32,7 @@ "//services/audio/public/cpp/typemaps.gni", "//services/device/public/mojom/typemaps.gni", "//services/identity/public/cpp/typemaps.gni", + "//services/media_session/public/cpp/typemaps.gni", "//services/network/public/cpp/typemaps.gni", "//services/preferences/public/cpp/typemaps.gni", "//services/proxy_resolver/public/cpp/typemaps.gni",
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py index 9fdbee3..d847f4b1 100755 --- a/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -370,9 +370,11 @@ args.gen_dir + "/", 1)[1] full_target_name = "//" + target_prefix_without_gen_dir.rsplit( "/", 1)[0] + ":" + target_name - print ">>> File \n\t%s\nfrom target \n\t%s\nis missing dependencies " + \ - "for the following imports:\n\t%s" % (args.filename[0], \ - full_target_name, list(mojom_imports.difference(sources))) + + print ">>> File \"%s\"" % (filename) + print ">>> from target \"%s\"" % (full_target_name) + print ">>> is missing dependencies for the following imports:\n%s" % \ + list(mojom_imports.difference(sources)) sys.exit(1) source_filename, _ = os.path.splitext(rel_path.relative_path())
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 3593abd..cb190cd 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -795,6 +795,12 @@ } } + if (network_ != NetworkChangeNotifier::kInvalidNetworkHandle && + network_ != factory_->default_network()) { + UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.MigrationBeforeHandshake", + rv == OK); + } + if (rv != OK) return rv;
diff --git a/remoting/android/BUILD.gn b/remoting/android/BUILD.gn index cc6902f8..0821d13 100644 --- a/remoting/android/BUILD.gn +++ b/remoting/android/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("//base/android/jni_generator/jni_exception_list.gni") import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//remoting/android/client_java_tmpl.gni") @@ -22,12 +21,6 @@ jni_package = "remoting" } -generate_jni_registration("remoting_jni_registration") { - target = ":remoting_apk" - output = "$root_gen_dir/remoting/client/${target_name}.h" - exception_files = jni_exception_files -} - _raw_resources_base_dir = "$target_gen_dir/credits_resources_raw/res" # The target is named this way, instead of "..._raw_resources", specifically
diff --git a/remoting/client/jni/BUILD.gn b/remoting/client/jni/BUILD.gn index 6d097626..34c08965 100644 --- a/remoting/client/jni/BUILD.gn +++ b/remoting/client/jni/BUILD.gn
@@ -19,7 +19,6 @@ shared_library("remoting_client_jni") { deps = [ "//remoting/android:jni_headers", - "//remoting/android:remoting_jni_registration", "//remoting/base", "//remoting/client", "//remoting/client/display", @@ -45,7 +44,11 @@ "android", "EGL", ] - configs += [ "//remoting/build/config:enable_webrtc_remoting_client" ] + configs -= [ "//build/config/android:hide_all_but_jni_onload" ] + configs += [ + "//build/config/android:hide_all_but_jni", + "//remoting/build/config:enable_webrtc_remoting_client", + ] assert_no_deps = [ "//third_party/ffmpeg:*" ] }
diff --git a/remoting/client/jni/remoting_jni_onload.cc b/remoting/client/jni/remoting_jni_onload.cc index bd60b3e..642f0ba 100644 --- a/remoting/client/jni/remoting_jni_onload.cc +++ b/remoting/client/jni/remoting_jni_onload.cc
@@ -4,16 +4,9 @@ #include "base/android/base_jni_onload.h" #include "base/android/jni_android.h" -#include "base/bind.h" -#include "base/macros.h" -#include "remoting/client/remoting_jni_registration.h" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { base::android::InitVM(vm); - JNIEnv* env = base::android::AttachCurrentThread(); - if (!RegisterMainDexNatives(env) || !RegisterNonMainDexNatives(env)) { - return -1; - } if (!base::android::OnJNIOnLoadInit()) { return -1;
diff --git a/services/BUILD.gn b/services/BUILD.gn index 4e4c493..548c724 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -58,6 +58,7 @@ deps += [ "//services/data_decoder/public/cpp/android:safe_json_java", "//services/device:java", + "//services/media_session/public/cpp/android:media_session_java", # Some tests make network requests. "//net/android:net_java",
diff --git a/services/device/hid/test_report_descriptors.cc b/services/device/hid/test_report_descriptors.cc index c76efca..0ba7a09 100644 --- a/services/device/hid/test_report_descriptors.cc +++ b/services/device/hid/test_report_descriptors.cc
@@ -4,6 +4,8 @@ #include "services/device/hid/test_report_descriptors.h" +#include "base/stl_util.h" + namespace device { // Digitizer descriptor from HID descriptor tool @@ -104,7 +106,7 @@ 0xc0, // End Collection 0xc0 // End Collection }; -const size_t kDigitizerSize = sizeof(kDigitizer); +const size_t kDigitizerSize = base::size(kDigitizer); // Keyboard descriptor from HID descriptor tool // http://www.usb.org/developers/hidpage/dt2_4.zip @@ -142,7 +144,7 @@ 0x81, 0x00, // Input (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) 0xc0 // End Collection }; -const size_t kKeyboardSize = sizeof(kKeyboard); +const size_t kKeyboardSize = base::size(kKeyboard); // Monitor descriptor from HID descriptor tool // http://www.usb.org/developers/hidpage/dt2_4.zip @@ -195,7 +197,7 @@ 0xb1, 0x02, // Feature (Dat|Arr|Rel|NoWrp|Lin|Prf|NoNull|BitF) 0xc0 // End Collection }; -const size_t kMonitorSize = sizeof(kMonitor); +const size_t kMonitorSize = base::size(kMonitor); // Mouse descriptor from HID descriptor tool // http://www.usb.org/developers/hidpage/dt2_4.zip @@ -227,7 +229,7 @@ 0xc0, // End Collection 0xc0 // End Collection }; -const size_t kMouseSize = sizeof(kMouse); +const size_t kMouseSize = base::size(kMouse); // Logitech Unifying receiver descriptor const uint8_t kLogitechUnifyingReceiver[] = { @@ -279,6 +281,1365 @@ 0x91, 0x00, // Output (Dat|Var|Rel|NoWrp|Lin|Prf|NoNull|BitF) 0xC0 // End Collection }; -const size_t kLogitechUnifyingReceiverSize = sizeof(kLogitechUnifyingReceiver); +const size_t kLogitechUnifyingReceiverSize = + base::size(kLogitechUnifyingReceiver); + +// http://eleccelerator.com/wiki/index.php?title=DualShock_4#HID_Report_Descriptor +const uint8_t kSonyDualshock3[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x04, // Usage (Joystick) + 0xA1, 0x01, // Collection (Physical) + 0xA1, 0x02, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position) NOTE: reserved byte + 0x75, 0x01, // Report Size (1) + 0x95, 0x13, // Report Count (19) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x01, // Physical Maximum (1) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x13, // Usage Maximum (0x13) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0D, // Report Count (13) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position) NOTE: 32 bit integer, + // where 0:18 are buttons and 19:31 are reserved + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Undefined) + 0x75, 0x08, // Report Size (8) + 0x95, 0x04, // Report Count (4) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0xFF, 0x00, // Physical Maximum (255) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x32, // Usage (Z) + 0x09, 0x35, // Usage (Rz) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position) NOTE: four joysticks + 0xC0, // End Collection + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x75, 0x08, // Report Size (8) + 0x95, 0x27, // Report Count (39) + 0x09, 0x01, // Usage (Pointer) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position) + 0x75, 0x08, // Report Size (8) + 0x95, 0x30, // Report Count (48) + 0x09, 0x01, // Usage (Pointer) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x75, 0x08, // Report Size (8) + 0x95, 0x30, // Report Count (48) + 0x09, 0x01, // Usage (Pointer) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0xC0, // End Collection + 0xA1, 0x02, // Collection (Application) + 0x85, 0x02, // Report ID (2) + 0x75, 0x08, // Report Size (8) + 0x95, 0x30, // Report Count (48) + 0x09, 0x01, // Usage (Pointer) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0xC0, // End Collection + 0xA1, 0x02, // Collection (Application) + 0x85, 0xEE, // Report ID (238) + 0x75, 0x08, // Report Size (8) + 0x95, 0x30, // Report Count (48) + 0x09, 0x01, // Usage (Pointer) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0xC0, // End Collection + 0xA1, 0x02, // Collection (Application) + 0x85, 0xEF, // Report ID (239) + 0x75, 0x08, // Report Size (8) + 0x95, 0x30, // Report Count (48) + 0x09, 0x01, // Usage (Pointer) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0xC0, // End Collection + 0xC0, // End Collection +}; +const size_t kSonyDualshock3Size = base::size(kSonyDualshock3); + +// http://eleccelerator.com/wiki/index.php?title=DualShock_4#HID_Report_Descriptor +const uint8_t kSonyDualshock4[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x32, // Usage (Z) + 0x09, 0x35, // Usage (Rz) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x04, // Report Count (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position) + 0x09, 0x39, // Usage (Hat switch) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x07, // Logical Maximum (7) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred + // State,Null State) + 0x65, 0x00, // Unit (None) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0E, // Usage Maximum (0x0E) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0E, // Report Count (14) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x20, // Usage (0x20) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x7F, // Logical Maximum (127) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x33, // Usage (Rx) + 0x09, 0x34, // Usage (Ry) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x02, // Report Count (2) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x21, // Usage (0x21) + 0x95, 0x36, // Report Count (54) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position) + 0x85, 0x05, // Report ID (5) + 0x09, 0x22, // Usage (0x22) + 0x95, 0x1F, // Report Count (31) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State, + // No Null Position,Non-volatile) + 0x85, 0x04, // Report ID (4) + 0x09, 0x23, // Usage (0x23) + 0x95, 0x24, // Report Count (36) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x02, // Report ID (2) + 0x09, 0x24, // Usage (0x24) + 0x95, 0x24, // Report Count (36) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x08, // Report ID (8) + 0x09, 0x25, // Usage (0x25) + 0x95, 0x03, // Report Count (3) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x10, // Report ID (16) + 0x09, 0x26, // Usage (0x26) + 0x95, 0x04, // Report Count (4) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x11, // Report ID (17) + 0x09, 0x27, // Usage (0x27) + 0x95, 0x02, // Report Count (2) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x12, // Report ID (18) + 0x06, 0x02, 0xFF, // Usage Page (Vendor Defined 0xFF02) + 0x09, 0x21, // Usage (0x21) + 0x95, 0x0F, // Report Count (15) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x13, // Report ID (19) + 0x09, 0x22, // Usage (0x22) + 0x95, 0x16, // Report Count (22) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x14, // Report ID (20) + 0x06, 0x05, 0xFF, // Usage Page (Vendor Defined 0xFF05) + 0x09, 0x20, // Usage (0x20) + 0x95, 0x10, // Report Count (16) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x15, // Report ID (21) + 0x09, 0x21, // Usage (0x21) + 0x95, 0x2C, // Report Count (44) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x06, 0x80, 0xFF, // Usage Page (Vendor Defined 0xFF80) + 0x85, 0x80, // Report ID (128) + 0x09, 0x20, // Usage (0x20) + 0x95, 0x06, // Report Count (6) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x81, // Report ID (129) + 0x09, 0x21, // Usage (0x21) + 0x95, 0x06, // Report Count (6) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x82, // Report ID (130) + 0x09, 0x22, // Usage (0x22) + 0x95, 0x05, // Report Count (5) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x83, // Report ID (131) + 0x09, 0x23, // Usage (0x23) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x84, // Report ID (132) + 0x09, 0x24, // Usage (0x24) + 0x95, 0x04, // Report Count (4) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x85, // Report ID (133) + 0x09, 0x25, // Usage (0x25) + 0x95, 0x06, // Report Count (6) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x86, // Report ID (134) + 0x09, 0x26, // Usage (0x26) + 0x95, 0x06, // Report Count (6) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x87, // Report ID (135) + 0x09, 0x27, // Usage (0x27) + 0x95, 0x23, // Report Count (35) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x88, // Report ID (136) + 0x09, 0x28, // Usage (0x28) + 0x95, 0x22, // Report Count (34) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x89, // Report ID (137) + 0x09, 0x29, // Usage (0x29) + 0x95, 0x02, // Report Count (2) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x90, // Report ID (144) + 0x09, 0x30, // Usage (0x30) + 0x95, 0x05, // Report Count (5) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x91, // Report ID (145) + 0x09, 0x31, // Usage (0x31) + 0x95, 0x03, // Report Count (3) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x92, // Report ID (146) + 0x09, 0x32, // Usage (0x32) + 0x95, 0x03, // Report Count (3) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0x93, // Report ID (147) + 0x09, 0x33, // Usage (0x33) + 0x95, 0x0C, // Report Count (12) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA0, // Report ID (160) + 0x09, 0x40, // Usage (0x40) + 0x95, 0x06, // Report Count (6) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA1, // Report ID (161) + 0x09, 0x41, // Usage (0x41) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA2, // Report ID (162) + 0x09, 0x42, // Usage (0x42) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA3, // Report ID (163) + 0x09, 0x43, // Usage (0x43) + 0x95, 0x30, // Report Count (48) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA4, // Report ID (164) + 0x09, 0x44, // Usage (0x44) + 0x95, 0x0D, // Report Count (13) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA5, // Report ID (165) + 0x09, 0x45, // Usage (0x45) + 0x95, 0x15, // Report Count (21) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA6, // Report ID (166) + 0x09, 0x46, // Usage (0x46) + 0x95, 0x15, // Report Count (21) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xF0, // Report ID (240) + 0x09, 0x47, // Usage (0x47) + 0x95, 0x3F, // Report Count (63) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xF1, // Report ID (241) + 0x09, 0x48, // Usage (0x48) + 0x95, 0x3F, // Report Count (63) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xF2, // Report ID (242) + 0x09, 0x49, // Usage (0x49) + 0x95, 0x0F, // Report Count (15) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA7, // Report ID (167) + 0x09, 0x4A, // Usage (0x4A) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA8, // Report ID (168) + 0x09, 0x4B, // Usage (0x4B) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xA9, // Report ID (169) + 0x09, 0x4C, // Usage (0x4C) + 0x95, 0x08, // Report Count (8) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAA, // Report ID (170) + 0x09, 0x4E, // Usage (0x4E) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAB, // Report ID (171) + 0x09, 0x4F, // Usage (0x4F) + 0x95, 0x39, // Report Count (57) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAC, // Report ID (172) + 0x09, 0x50, // Usage (0x50) + 0x95, 0x39, // Report Count (57) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAD, // Report ID (173) + 0x09, 0x51, // Usage (0x51) + 0x95, 0x0B, // Report Count (11) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAE, // Report ID (174) + 0x09, 0x52, // Usage (0x52) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xAF, // Report ID (175) + 0x09, 0x53, // Usage (0x53) + 0x95, 0x02, // Report Count (2) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0x85, 0xB0, // Report ID (176) + 0x09, 0x54, // Usage (0x54) + 0x95, 0x3F, // Report Count (63) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred + // State,No Null Position,Non-volatile) + 0xC0, // End Collection + +}; +const size_t kSonyDualshock4Size = base::size(kSonyDualshock4); + +const uint8_t kMicrosoftXboxWirelessController[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x33, // Usage (Rx) + 0x09, 0x34, // Usage (Ry) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x32, // Usage (Z) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x35, // Usage (Rz) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x39, // Usage (Hat switch) + 0x15, 0x01, // Logical Minimum (1) + 0x25, 0x08, // Logical Maximum (8) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: + // Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,Null State) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x00, // Physical Maximum (0) + 0x65, 0x00, // Unit (None) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0A, // Usage Maximum (0x0A) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0A, // Report Count (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x80, // Usage (Sys Control) + 0x85, 0x02, // Report ID (2) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x85, // Usage (Sys Main Menu) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x01, // Report Count (1) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x07, // Report Size (7) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x0F, // Usage Page (PID Page) + 0x09, 0x21, // Usage (0x21) + 0x85, 0x03, // Report ID (3) + 0xA1, 0x02, // Collection (Logical) + 0x09, 0x97, // Usage (0x97) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x70, // Usage (0x70) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x04, // Report Count (4) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x50, // Usage (0x50) + 0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: + // Seconds) + 0x55, 0x0E, // Unit Exponent (-2) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0xA7, // Usage (0xA7) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x65, 0x00, // Unit (None) + 0x55, 0x00, // Unit Exponent (0) + 0x09, 0x7C, // Usage (0x7C) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0xC0, // End Collection + 0x85, 0x04, // Report ID (4) + 0x05, 0x06, // Usage Page (Generic Dev Ctrls) + 0x09, 0x20, // Usage (Battery Strength) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null + // Position) + 0xC0, // End Collection + 0x00, // Unknown (bTag: 0x00, bType: 0x00) +}; +const size_t kMicrosoftXboxWirelessControllerSize = + base::size(kMicrosoftXboxWirelessController); + +const uint8_t kNintendoSwitchProController[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x15, 0x00, // Logical Minimum (0) + 0x09, 0x04, // Usage (Joystick) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x30, // Report ID (48) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0A, // Usage Maximum (0x0A) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0A, // Report Count (10) + 0x55, 0x00, // Unit Exponent (0) + 0x65, 0x00, // Unit (None) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x0B, // Usage Minimum (0x0B) + 0x29, 0x0E, // Usage Maximum (0x0E) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x04, // Report Count (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x75, 0x01, // Report Size (1) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0B, 0x01, 0x00, 0x01, 0x00, // Usage (0x010001) + 0xA1, 0x00, // Collection (Physical) + 0x0B, 0x30, 0x00, 0x01, 0x00, // Usage (0x010030) + 0x0B, 0x31, 0x00, 0x01, 0x00, // Usage (0x010031) + 0x0B, 0x32, 0x00, 0x01, 0x00, // Usage (0x010032) + 0x0B, 0x35, 0x00, 0x01, 0x00, // Usage (0x010035) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x75, 0x10, // Report Size (16) + 0x95, 0x04, // Report Count (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x0B, 0x39, 0x00, 0x01, 0x00, // Usage (0x010039) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x07, // Logical Maximum (7) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x65, 0x14, // Unit (System: English Rotation, Length: + // Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x0F, // Usage Minimum (0x0F) + 0x29, 0x12, // Usage Maximum (0x12) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x04, // Report Count (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x75, 0x08, // Report Size (8) + 0x95, 0x34, // Report Count (52) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x85, 0x21, // Report ID (33) + 0x09, 0x01, // Usage (0x01) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x85, 0x81, // Report ID (-127) + 0x09, 0x02, // Usage (0x02) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x85, 0x01, // Report ID (1) + 0x09, 0x03, // Usage (0x03) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x91, 0x83, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Volatile) + 0x85, 0x10, // Report ID (16) + 0x09, 0x04, // Usage (0x04) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x91, 0x83, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Volatile) + 0x85, 0x80, // Report ID (-128) + 0x09, 0x05, // Usage (0x05) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x91, 0x83, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Volatile) + 0x85, 0x82, // Report ID (-126) + 0x09, 0x06, // Usage (0x06) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3F, // Report Count (63) + 0x91, 0x83, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Volatile) + 0xC0, // End Collection +}; +const size_t kNintendoSwitchProControllerSize = + base::size(kNintendoSwitchProController); + +const uint8_t kMicrosoftXboxAdaptiveController[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x32, // Usage (Z) + 0x09, 0x35, // Usage (Rz) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x02, // Usage Page (Sim Ctrls) + 0x09, 0xC5, // Usage (Brake) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x02, // Usage Page (Sim Ctrls) + 0x09, 0xC4, // Usage (Accelerator) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x39, // Usage (Hat switch) + 0x15, 0x01, // Logical Minimum (1) + 0x25, 0x08, // Logical Maximum (8) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: + // Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,Null State) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x00, // Physical Maximum (0) + 0x65, 0x00, // Unit (None) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0F, // Usage Maximum (0x0F) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0F, // Report Count (15) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x01, // Report Size (1) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x0C, // Usage Page (Consumer) + 0x0A, 0x24, 0x02, // Usage (AC Back) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x01, // Report Count (1) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x07, // Report Size (7) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x40, // Usage (Vx) + 0x09, 0x41, // Usage (Vy) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x43, // Usage (Vbrx) + 0x09, 0x44, // Usage (Vbry) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) + 0x95, 0x02, // Report Count (2) + 0x75, 0x10, // Report Size (16) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x42, // Usage (Vz) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x45, // Usage (Vbrz) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x03, // Logical Maximum (1023) + 0x95, 0x01, // Report Count (1) + 0x75, 0x0A, // Report Size (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x06, // Report Size (6) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x37, // Usage (Dial) + 0x15, 0x01, // Logical Minimum (1) + 0x25, 0x08, // Logical Maximum (8) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: + // Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,Null State) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x00, // Physical Maximum (0) + 0x65, 0x00, // Unit (None) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x10, // Usage Minimum (0x10) + 0x29, 0x1E, // Usage Maximum (0x1E) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0F, // Report Count (15) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x01, // Report Size (1) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x0C, // Usage Page (Consumer) + 0x0A, 0x82, 0x00, // Usage (Mode Step) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x01, // Report Count (1) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x07, // Report Size (7) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x05, 0x0C, // Usage Page (Consumer) + 0x09, 0x01, // Usage (Consumer Control) + 0xA1, 0x01, // Collection (Application) + 0x0A, 0x81, 0x00, // Usage (Assign Selection) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0x84, 0x00, // Usage (Enter Channel) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0x85, 0x00, // Usage (Order Movie) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0x99, 0x00, // Usage (Media Select Security) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x95, 0x01, // Report Count (1) + 0x75, 0x04, // Report Size (4) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0x9E, 0x00, // Usage (Media Select SAP) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xA1, 0x00, // Usage (Once) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xA2, 0x00, // Usage (Daily) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xA3, 0x00, // Usage (Weekly) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xA4, 0x00, // Usage (Monthly) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xB9, 0x00, // Usage (Random Play) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xBA, 0x00, // Usage (Select Disc) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xBB, 0x00, // Usage (Enter Disc) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xBE, 0x00, // Usage (Track Normal) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC0, 0x00, // Usage (Frame Forward) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC1, 0x00, // Usage (Frame Back) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC2, 0x00, // Usage (Mark) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC3, 0x00, // Usage (Clear Mark) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC4, 0x00, // Usage (Repeat From Mark) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC5, 0x00, // Usage (Return To Mark) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC6, 0x00, // Usage (Search Mark Forward) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC7, 0x00, // Usage (Search Mark Backwards) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x0A, 0xC8, 0x00, // Usage (Counter Reset) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x0C, // Usage Page (Consumer) + 0x09, 0x01, // Usage (Consumer Control) + 0x85, 0x02, // Report ID (2) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x0C, // Usage Page (Consumer) + 0x0A, 0x23, 0x02, // Usage (AC Home) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x01, // Report Count (1) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x07, // Report Size (7) + 0x95, 0x01, // Report Count (1) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x05, 0x0F, // Usage Page (PID Page) + 0x09, 0x21, // Usage (0x21) + 0x85, 0x03, // Report ID (3) + 0xA1, 0x02, // Collection (Logical) + 0x09, 0x97, // Usage (0x97) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x00, // Logical Maximum (0) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x70, // Usage (0x70) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x04, // Report Count (4) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x50, // Usage (0x50) + 0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: + // Seconds) + 0x55, 0x0E, // Unit Exponent (-2) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0xA7, // Usage (0xA7) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x65, 0x00, // Unit (None) + 0x55, 0x00, // Unit Exponent (0) + 0x09, 0x7C, // Usage (0x7C) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0xC0, // End Collection + 0x05, 0x06, // Usage Page (Generic Dev Ctrls) + 0x09, 0x20, // Usage (Battery Strength) + 0x85, 0x04, // Report ID (4) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0xA1, 0x02, // Collection (Logical) + 0x85, 0x06, // Report ID (6) + 0x09, 0x01, // Usage (0x01) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x02, // Usage (0x02) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x03, // Usage (0x03) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x04, // Usage (0x04) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3C, // Report Count (60) + 0xB2, 0x02, 0x01, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile,Buffered Bytes) + 0xC0, // End Collection + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x02, // Usage (0x02) + 0xA1, 0x02, // Collection (Logical) + 0x85, 0x07, // Report ID (7) + 0x09, 0x05, // Usage (0x05) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x06, // Usage (0x06) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x07, // Usage (0x07) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0xC0, // End Collection + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x03, // Usage (0x03) + 0xA1, 0x02, // Collection (Logical) + 0x85, 0x08, // Report ID (8) + 0x09, 0x08, // Usage (0x08) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x09, // Usage (0x09) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x0A, // Usage (0x0A) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0xC0, // End Collection + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x04, // Usage (0x04) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x09, // Report ID (9) + 0x09, 0x0B, // Usage (0x0B) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x0C, // Usage (0x0C) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x0D, // Usage (0x0D) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x0E, // Usage (0x0E) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0x09, 0x0F, // Usage (0x0F) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x3C, // Report Count (60) + 0xB2, 0x02, 0x01, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile,Buffered Bytes) + 0xC0, // End Collection + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x05, // Usage (0x05) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x0A, // Report ID (10) + 0x09, 0x10, // Usage (0x10) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, // Logical Maximum (2147483646) + 0x75, 0x20, // Report Size (32) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x09, 0x11, // Usage (0x11) + 0x15, 0x00, // Logical Minimum (0) + 0x27, 0xFF, 0xFF, 0xFF, 0x7F, // Logical Maximum (2147483646) + 0x75, 0x20, // Report Size (32) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x09, 0x12, // Usage (0x12) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x02, // Report Count (2) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x09, 0x13, // Usage (0x13) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x06, // Usage (0x06) + 0xA1, 0x02, // Collection (Logical) + 0x85, 0x0B, // Report ID (11) + 0x09, 0x14, // Usage (0x14) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x64, // Logical Maximum (100) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position, + // Non-volatile) + 0xC0, // End Collection + 0xC0, // End Collection + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x05, // Report ID (5) + 0x05, 0x07, // Usage Page (Kbrd/Keypad) + 0x19, 0xE0, // Usage Minimum (0xE0) + 0x29, 0xE7, // Usage Maximum (0xE7) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x65, // Logical Maximum (101) + 0x05, 0x07, // Usage Page (Kbrd/Keypad) + 0x19, 0x00, // Usage Minimum (0x00) + 0x29, 0x65, // Usage Maximum (0x65) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear, + // Preferred State,No Null Position) + 0xC0, // End Collection + 0x00, // Unknown (bTag: 0x00, bType: 0x00) +}; +const size_t kMicrosoftXboxAdaptiveControllerSize = + base::size(kMicrosoftXboxAdaptiveController); } // namespace device
diff --git a/services/device/hid/test_report_descriptors.h b/services/device/hid/test_report_descriptors.h index f3b4f8b7..1985ce6 100644 --- a/services/device/hid/test_report_descriptors.h +++ b/services/device/hid/test_report_descriptors.h
@@ -34,6 +34,26 @@ extern const uint8_t kLogitechUnifyingReceiver[]; extern const size_t kLogitechUnifyingReceiverSize; +// Sony Dualshock 3 USB descriptor +extern const uint8_t kSonyDualshock3[]; +extern const size_t kSonyDualshock3Size; + +// Sony Dualshock 4 USB descriptor +extern const uint8_t kSonyDualshock4[]; +extern const size_t kSonyDualshock4Size; + +// Microsoft Xbox Wireless Controller Bluetooth descriptor +extern const uint8_t kMicrosoftXboxWirelessController[]; +extern const size_t kMicrosoftXboxWirelessControllerSize; + +// Nintendo Switch Pro Controller USB descriptor +extern const uint8_t kNintendoSwitchProController[]; +extern const size_t kNintendoSwitchProControllerSize; + +// Microsoft Xbox Adaptive Controller Bluetooth descriptor +extern const uint8_t kMicrosoftXboxAdaptiveController[]; +extern const size_t kMicrosoftXboxAdaptiveControllerSize; + } // namespace device #endif // SERVICES_DEVICE_HID_TEST_REPORT_DESCRIPTORS_H_
diff --git a/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc b/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc index c365eb66..9fa56aa 100644 --- a/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc +++ b/services/device/public/cpp/hid/hid_report_descriptor_unittest.cc
@@ -22,7 +22,7 @@ using HidCollectionInfo = mojom::HidCollectionInfo; using HidCollectionInfoPtr = mojom::HidCollectionInfoPtr; - void SetUp() override { descriptor_ = NULL; } + void SetUp() override { descriptor_ = nullptr; } void TearDown() override { if (descriptor_) { @@ -32,7 +32,7 @@ public: void ValidateDetails( - const std::vector<HidCollectionInfoPtr>& expected_collections, + const std::vector<HidCollectionInfoPtr>& expected_collection_infos, const bool expected_has_report_id, const size_t expected_max_input_report_size, const size_t expected_max_output_report_size, @@ -42,36 +42,34 @@ descriptor_ = new HidReportDescriptor(std::vector<uint8_t>(bytes, bytes + size)); - std::vector<HidCollectionInfoPtr> actual_collections; + std::vector<HidCollectionInfoPtr> actual_collection_infos; bool actual_has_report_id; size_t actual_max_input_report_size; size_t actual_max_output_report_size; size_t actual_max_feature_report_size; - descriptor_->GetDetails(&actual_collections, &actual_has_report_id, + descriptor_->GetDetails(&actual_collection_infos, &actual_has_report_id, &actual_max_input_report_size, &actual_max_output_report_size, &actual_max_feature_report_size); - ASSERT_EQ(expected_collections.size(), actual_collections.size()); + ASSERT_EQ(expected_collection_infos.size(), actual_collection_infos.size()); - auto actual_collections_iter = actual_collections.begin(); - auto expected_collections_iter = expected_collections.begin(); + auto actual_info_iter = actual_collection_infos.begin(); + auto expected_info_iter = expected_collection_infos.begin(); - while (expected_collections_iter != expected_collections.end() && - actual_collections_iter != actual_collections.end()) { - const HidCollectionInfoPtr& expected_collection = - *expected_collections_iter; - const HidCollectionInfoPtr& actual_collection = *actual_collections_iter; + while (expected_info_iter != expected_collection_infos.end() && + actual_info_iter != actual_collection_infos.end()) { + const HidCollectionInfoPtr& expected_info = *expected_info_iter; + const HidCollectionInfoPtr& actual_info = *actual_info_iter; - ASSERT_EQ(expected_collection->usage->usage_page, - actual_collection->usage->usage_page); - ASSERT_EQ(expected_collection->usage->usage, - actual_collection->usage->usage); - ASSERT_THAT(actual_collection->report_ids, - testing::ContainerEq(expected_collection->report_ids)); + ASSERT_EQ(expected_info->usage->usage_page, + actual_info->usage->usage_page); + ASSERT_EQ(expected_info->usage->usage, actual_info->usage->usage); + ASSERT_THAT(actual_info->report_ids, + testing::ContainerEq(expected_info->report_ids)); - expected_collections_iter++; - actual_collections_iter++; + ++expected_info_iter; + ++actual_info_iter; } ASSERT_EQ(expected_has_report_id, actual_has_report_id); @@ -85,63 +83,168 @@ }; TEST_F(HidReportDescriptorTest, ValidateDetails_Digitizer) { + const uint16_t usage_page = mojom::kPageDigitizer; + const uint16_t usage = 0x01; // Digitizer + auto digitizer = HidCollectionInfo::New(); - digitizer->usage = HidUsageAndPage::New(0x01, mojom::kPageDigitizer); - digitizer->report_ids.push_back(1); - digitizer->report_ids.push_back(2); - digitizer->report_ids.push_back(3); - std::vector<HidCollectionInfoPtr> expected; - expected.push_back(std::move(digitizer)); - ValidateDetails(expected, true, 6, 0, 0, kDigitizer, kDigitizerSize); + digitizer->usage = HidUsageAndPage::New(usage, usage_page); + digitizer->report_ids = {0x01, 0x02, 0x03}; + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(digitizer)); + ValidateDetails(expected_infos, true, 6, 0, 0, kDigitizer, kDigitizerSize); } TEST_F(HidReportDescriptorTest, ValidateDetails_Keyboard) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopKeyboard; + auto keyboard = HidCollectionInfo::New(); - keyboard->usage = HidUsageAndPage::New(0x06, mojom::kPageGenericDesktop); - std::vector<HidCollectionInfoPtr> expected; - expected.push_back(std::move(keyboard)); - ValidateDetails(expected, false, 8, 1, 0, kKeyboard, kKeyboardSize); + keyboard->usage = HidUsageAndPage::New(usage, usage_page); + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(keyboard)); + ValidateDetails(expected_infos, false, 8, 1, 0, kKeyboard, kKeyboardSize); } TEST_F(HidReportDescriptorTest, ValidateDetails_Monitor) { + const uint16_t usage_page = mojom::kPageMonitor0; // USB monitor + const uint16_t usage = 0x01; // Monitor control + auto monitor = HidCollectionInfo::New(); - monitor->usage = HidUsageAndPage::New(0x01, mojom::kPageMonitor0); - monitor->report_ids.push_back(1); - monitor->report_ids.push_back(2); - monitor->report_ids.push_back(3); - monitor->report_ids.push_back(4); - monitor->report_ids.push_back(5); - std::vector<HidCollectionInfoPtr> expected; - expected.push_back(std::move(monitor)); - ValidateDetails(expected, true, 0, 0, 243, kMonitor, kMonitorSize); + monitor->usage = HidUsageAndPage::New(usage, usage_page); + monitor->report_ids = {1, 2, 3, 4, 5}; + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(monitor)); + ValidateDetails(expected_infos, true, 0, 0, 243, kMonitor, kMonitorSize); } TEST_F(HidReportDescriptorTest, ValidateDetails_Mouse) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopMouse; + auto mouse = HidCollectionInfo::New(); - mouse->usage = HidUsageAndPage::New(0x02, mojom::kPageGenericDesktop); - std::vector<HidCollectionInfoPtr> expected; - expected.push_back(std::move(mouse)); - ValidateDetails(expected, false, 3, 0, 0, kMouse, kMouseSize); + mouse->usage = HidUsageAndPage::New(usage, usage_page); + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(mouse)); + ValidateDetails(expected_infos, false, 3, 0, 0, kMouse, kMouseSize); } TEST_F(HidReportDescriptorTest, ValidateDetails_LogitechUnifyingReceiver) { - auto hidpp_short = HidCollectionInfo::New(); - hidpp_short->usage = HidUsageAndPage::New(0x01, mojom::kPageVendor); - hidpp_short->report_ids.push_back(0x10); - auto hidpp_long = HidCollectionInfo::New(); - hidpp_long->usage = HidUsageAndPage::New(0x02, mojom::kPageVendor); - hidpp_long->report_ids.push_back(0x11); - auto hidpp_dj = HidCollectionInfo::New(); - hidpp_dj->usage = HidUsageAndPage::New(0x04, mojom::kPageVendor); - hidpp_dj->report_ids.push_back(0x20); - hidpp_dj->report_ids.push_back(0x21); + const uint16_t usage_page = mojom::kPageVendor; + const uint16_t usage_hidpp_short = 0x01; // Vendor-defined + const uint16_t usage_hidpp_long = 0x02; // Vendor-defined + const uint16_t usage_hidpp_dj = 0x04; // Vendor-defined - std::vector<HidCollectionInfoPtr> expected; - expected.push_back(std::move(hidpp_short)); - expected.push_back(std::move(hidpp_long)); - expected.push_back(std::move(hidpp_dj)); - ValidateDetails(expected, true, 31, 31, 0, kLogitechUnifyingReceiver, + auto hidpp_short = HidCollectionInfo::New(); + hidpp_short->usage = HidUsageAndPage::New(usage_hidpp_short, usage_page); + hidpp_short->report_ids = {0x10}; + auto hidpp_long = HidCollectionInfo::New(); + hidpp_long->usage = HidUsageAndPage::New(usage_hidpp_long, usage_page); + hidpp_long->report_ids = {0x11}; + auto hidpp_dj = HidCollectionInfo::New(); + hidpp_dj->usage = HidUsageAndPage::New(usage_hidpp_dj, usage_page); + hidpp_dj->report_ids = {0x20, 0x21}; + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(hidpp_short)); + expected_infos.push_back(std::move(hidpp_long)); + expected_infos.push_back(std::move(hidpp_dj)); + ValidateDetails(expected_infos, true, 31, 31, 0, kLogitechUnifyingReceiver, kLogitechUnifyingReceiverSize); } +TEST_F(HidReportDescriptorTest, ValidateDetails_SonyDualshock3) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopJoystick; + + auto top_info = HidCollectionInfo::New(); + top_info->usage = HidUsageAndPage::New(usage, usage_page); + top_info->report_ids = {0x01, 0x02, 0xee, 0xef}; + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(top_info)); + ValidateDetails(expected_infos, true, 48, 48, 48, kSonyDualshock3, + kSonyDualshock3Size); +} + +TEST_F(HidReportDescriptorTest, ValidateDetails_SonyDualshock4) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopGamePad; + + auto top_info = HidCollectionInfo::New(); + top_info->usage = HidUsageAndPage::New(usage, usage_page); + top_info->report_ids = {0x01, 0x05, 0x04, 0x02, 0x08, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x90, 0x91, 0x92, 0x93, 0xa0, 0xa1, + 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xf0, 0xf1, 0xf2, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0}; + + std::vector<HidCollectionInfoPtr> expected_infos; + expected_infos.push_back(std::move(top_info)); + ValidateDetails(expected_infos, true, 63, 31, 63, kSonyDualshock4, + kSonyDualshock4Size); +} + +TEST_F(HidReportDescriptorTest, ValidateDetails_XboxWirelessController) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopGamePad; + + auto top_info = HidCollectionInfo::New(); + top_info->usage = HidUsageAndPage::New(usage, usage_page); + top_info->report_ids = {0x01, 0x02, 0x03, 0x04}; + + std::vector<HidCollectionInfoPtr> expected_info; + expected_info.push_back(std::move(top_info)); + ValidateDetails(expected_info, true, 15, 8, 0, + kMicrosoftXboxWirelessController, + kMicrosoftXboxWirelessControllerSize); +} + +TEST_F(HidReportDescriptorTest, ValidateDetails_NintendoSwitchProController) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage = mojom::kGenericDesktopJoystick; + + auto top_info = HidCollectionInfo::New(); + top_info->usage = HidUsageAndPage::New(usage, usage_page); + top_info->report_ids = {0x30, 0x21, 0x81, 0x01, 0x10, 0x80, 0x82}; + + std::vector<HidCollectionInfoPtr> expected_info; + expected_info.push_back(std::move(top_info)); + ValidateDetails(expected_info, true, 63, 63, 0, kNintendoSwitchProController, + kNintendoSwitchProControllerSize); +} + +TEST_F(HidReportDescriptorTest, ValidateDetails_XboxAdaptiveController) { + const uint16_t usage_page = mojom::kPageGenericDesktop; + const uint16_t usage_gamepad = mojom::kGenericDesktopGamePad; + const uint16_t usage_keyboard = mojom::kGenericDesktopKeyboard; + const uint8_t report_ids_gamepad[] = {0x01, 0x02, 0x03, 0x04, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b}; + const size_t report_ids_gamepad_size = base::size(report_ids_gamepad); + const uint8_t report_ids_keyboard[] = {0x05}; + const size_t report_ids_keyboard_size = base::size(report_ids_keyboard); + + auto gamepad_info = HidCollectionInfo::New(); + gamepad_info->usage = HidUsageAndPage::New(usage_gamepad, usage_page); + gamepad_info->report_ids.insert(gamepad_info->report_ids.begin(), + report_ids_gamepad, + report_ids_gamepad + report_ids_gamepad_size); + + auto keyboard_info = HidCollectionInfo::New(); + keyboard_info->usage = HidUsageAndPage::New(usage_keyboard, usage_page); + keyboard_info->report_ids.insert( + keyboard_info->report_ids.begin(), report_ids_keyboard, + report_ids_keyboard + report_ids_keyboard_size); + + std::vector<HidCollectionInfoPtr> expected_info; + expected_info.push_back(std::move(gamepad_info)); + expected_info.push_back(std::move(keyboard_info)); + ValidateDetails(expected_info, true, 54, 8, 64, + kMicrosoftXboxAdaptiveController, + kMicrosoftXboxAdaptiveControllerSize); +} + } // namespace device
diff --git a/services/media_session/DEPS b/services/media_session/DEPS new file mode 100644 index 0000000..b8a225f --- /dev/null +++ b/services/media_session/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+jni", + "+ui/gfx", +]
diff --git a/services/media_session/public/cpp/BUILD.gn b/services/media_session/public/cpp/BUILD.gn index 0f6b88d7..3b90b616 100644 --- a/services/media_session/public/cpp/BUILD.gn +++ b/services/media_session/public/cpp/BUILD.gn
@@ -6,15 +6,24 @@ output_name = "media_session_cpp" sources = [ + "media_metadata.cc", + "media_metadata.h", "switches.cc", "switches.h", ] deps = [ "//base", + "//ui/gfx/geometry", + "//url", ] configs += [ "//build/config/compiler:wexit_time_destructors" ] + if (is_android) { + sources += [ "media_metadata_android.cc" ] + deps += [ "android:media_session_jni_headers" ] + } + defines = [ "IS_MEDIA_SESSION_CPP_IMPL" ] }
diff --git a/services/media_session/public/cpp/OWNERS b/services/media_session/public/cpp/OWNERS new file mode 100644 index 0000000..7aebc8abb --- /dev/null +++ b/services/media_session/public/cpp/OWNERS
@@ -0,0 +1,4 @@ +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/media_session/public/cpp/android/BUILD.gn b/services/media_session/public/cpp/android/BUILD.gn new file mode 100644 index 0000000..c7de4d2a --- /dev/null +++ b/services/media_session/public/cpp/android/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +_jni_sources = + [ "java/src/org/chromium/services/media_session/MediaMetadata.java" ] + +generate_jni("media_session_jni_headers") { + sources = _jni_sources + jni_package = "media_metadata" +} + +if (current_toolchain == default_toolchain) { + android_library("media_session_java") { + deps = [ + "//base:base_java", + ] + java_files = _jni_sources + } +}
diff --git a/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java similarity index 88% rename from content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java rename to services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java index a90faad..ce06aae 100644 --- a/content/public/android/java/src/org/chromium/content_public/common/MediaMetadata.java +++ b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java
@@ -1,8 +1,8 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 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.content_public.common; +package org.chromium.services.media_session; import android.graphics.Rect; import android.support.annotation.NonNull; @@ -16,13 +16,13 @@ /** * The MediaMetadata class carries information related to a media session. It is - * the Java counterpart of content::MediaMetadata. + * the Java counterpart of media_session::MediaMetadata. */ -@JNINamespace("content") +@JNINamespace("media_session") public final class MediaMetadata { /** * The MediaImage class carries the artwork information in MediaMetadata. It is the Java - * counterpart of content::MediaMetadata::MediaImage. + * counterpart of media_session::MediaMetadata::MediaImage. */ public static final class MediaImage { @NonNull @@ -91,8 +91,7 @@ if (!(obj instanceof MediaImage)) return false; MediaImage other = (MediaImage) obj; - return TextUtils.equals(mSrc, other.mSrc) - && TextUtils.equals(mType, other.mType) + return TextUtils.equals(mSrc, other.mSrc) && TextUtils.equals(mType, other.mType) && mSizes.equals(other.mSizes); } @@ -179,7 +178,7 @@ */ @CalledByNative private void createAndAddMediaImage(String src, String type, int[] flattenedSizes) { - assert (flattenedSizes.length % 2) == 0; + assert(flattenedSizes.length % 2) == 0; List<Rect> sizes = new ArrayList<Rect>(); for (int i = 0; (i + 1) < flattenedSizes.length; i += 2) { sizes.add(new Rect(0, 0, flattenedSizes[i], flattenedSizes[i + 1])); @@ -193,8 +192,7 @@ */ @CalledByNative private static MediaMetadata create(String title, String artist, String album) { - return new MediaMetadata(title == null ? "" : title, artist == null ? "" : artist, - album == null ? "" : album); + return new MediaMetadata(title, artist, album); } /** @@ -215,10 +213,8 @@ if (!(obj instanceof MediaMetadata)) return false; MediaMetadata other = (MediaMetadata) obj; - return TextUtils.equals(mTitle, other.mTitle) - && TextUtils.equals(mArtist, other.mArtist) - && TextUtils.equals(mAlbum, other.mAlbum) - && mArtwork.equals(other.mArtwork); + return TextUtils.equals(mTitle, other.mTitle) && TextUtils.equals(mArtist, other.mArtist) + && TextUtils.equals(mAlbum, other.mAlbum) && mArtwork.equals(other.mArtwork); } /**
diff --git a/services/media_session/public/cpp/media_metadata.cc b/services/media_session/public/cpp/media_metadata.cc new file mode 100644 index 0000000..79468f9 --- /dev/null +++ b/services/media_session/public/cpp/media_metadata.cc
@@ -0,0 +1,38 @@ +// Copyright 2018 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 "services/media_session/public/cpp/media_metadata.h" + +#include <algorithm> +#include <iterator> + +namespace media_session { + +MediaMetadata::MediaImage::MediaImage() = default; + +MediaMetadata::MediaImage::MediaImage(const MediaImage& other) = default; + +MediaMetadata::MediaImage::~MediaImage() = default; + +bool MediaMetadata::MediaImage::operator==( + const MediaMetadata::MediaImage& other) const { + return src == other.src && type == other.type && sizes == other.sizes; +} + +MediaMetadata::MediaMetadata() = default; + +MediaMetadata::~MediaMetadata() = default; + +MediaMetadata::MediaMetadata(const MediaMetadata& other) = default; + +bool MediaMetadata::operator==(const MediaMetadata& other) const { + return title == other.title && artist == other.artist && + album == other.album && artwork == other.artwork; +} + +bool MediaMetadata::operator!=(const MediaMetadata& other) const { + return !(*this == other); +} + +} // namespace media_session
diff --git a/services/media_session/public/cpp/media_metadata.h b/services/media_session/public/cpp/media_metadata.h new file mode 100644 index 0000000..471737fa --- /dev/null +++ b/services/media_session/public/cpp/media_metadata.h
@@ -0,0 +1,81 @@ +// Copyright 2018 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_ +#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_ + +#include <vector> + +#include "base/component_export.h" +#include "base/strings/string16.h" +#include "build/build_config.h" +#include "ui/gfx/geometry/size.h" +#include "url/gurl.h" + +#if defined(OS_ANDROID) + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" + +#endif // defined(OS_ANDROID) + +namespace media_session { + +// The MediaMetadata is a structure carrying information associated to a +// MediaSession. +struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaMetadata { + // Structure representing an MediaImage as per the MediaSession API, see: + // https://wicg.github.io/mediasession/#dictdef-mediaimage + struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaImage { + MediaImage(); + MediaImage(const MediaImage& other); + ~MediaImage(); + + bool operator==(const MediaImage& other) const; + + // MUST be a valid url. If an icon doesn't have a valid URL, it will not be + // successfully parsed, thus will not be represented in the Manifest. + GURL src; + + // Empty if the parsing failed or the field was not present. The type can be + // any string and doesn't have to be a valid image MIME type at this point. + // It is up to the consumer of the object to check if the type matches a + // supported type. + base::string16 type; + + // Empty if the parsing failed, the field was not present or empty. + // The special value "any" is represented by gfx::Size(0, 0). + std::vector<gfx::Size> sizes; + }; + + MediaMetadata(); + ~MediaMetadata(); + + MediaMetadata(const MediaMetadata& other); + + bool operator==(const MediaMetadata& other) const; + bool operator!=(const MediaMetadata& other) const; + +#if defined(OS_ANDROID) + // Creates a Java MediaMetadata instance and returns the JNI ref. + base::android::ScopedJavaLocalRef<jobject> CreateJavaObject(JNIEnv* env); +#endif + + // Title associated to the MediaSession. + base::string16 title; + + // Artist associated to the MediaSession. + base::string16 artist; + + // Album associated to the MediaSession. + base::string16 album; + + // Artwork associated to the MediaSession. + std::vector<MediaImage> artwork; +}; + +} // namespace media_session + +#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_METADATA_H_
diff --git a/services/media_session/public/cpp/media_metadata_android.cc b/services/media_session/public/cpp/media_metadata_android.cc new file mode 100644 index 0000000..346ebf2 --- /dev/null +++ b/services/media_session/public/cpp/media_metadata_android.cc
@@ -0,0 +1,60 @@ +// Copyright 2018 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 "services/media_session/public/cpp/media_metadata.h" + +#include <string> +#include <vector> + +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "jni/MediaMetadata_jni.h" + +using base::android::ScopedJavaLocalRef; + +namespace media_session { + +namespace { + +std::vector<int> GetFlattenedSizeArray(const std::vector<gfx::Size>& sizes) { + std::vector<int> flattened_array; + flattened_array.reserve(2 * sizes.size()); + for (const auto& size : sizes) { + flattened_array.push_back(size.width()); + flattened_array.push_back(size.height()); + } + return flattened_array; +} + +} // anonymous namespace + +base::android::ScopedJavaLocalRef<jobject> MediaMetadata::CreateJavaObject( + JNIEnv* env) { + ScopedJavaLocalRef<jstring> j_title( + base::android::ConvertUTF16ToJavaString(env, title)); + ScopedJavaLocalRef<jstring> j_artist( + base::android::ConvertUTF16ToJavaString(env, artist)); + ScopedJavaLocalRef<jstring> j_album( + base::android::ConvertUTF16ToJavaString(env, album)); + + ScopedJavaLocalRef<jobject> j_metadata = + Java_MediaMetadata_create(env, j_title, j_artist, j_album); + + for (const auto& image : artwork) { + std::string src = image.src.spec(); + ScopedJavaLocalRef<jstring> j_src( + base::android::ConvertUTF8ToJavaString(env, src)); + ScopedJavaLocalRef<jstring> j_type( + base::android::ConvertUTF16ToJavaString(env, image.type)); + ScopedJavaLocalRef<jintArray> j_sizes( + base::android::ToJavaIntArray(env, GetFlattenedSizeArray(image.sizes))); + + Java_MediaMetadata_createAndAddMediaImage(env, j_metadata, j_src, j_type, + j_sizes); + } + + return j_metadata; +} + +} // namespace media_session
diff --git a/services/media_session/public/cpp/media_session.typemap b/services/media_session/public/cpp/media_session.typemap new file mode 100644 index 0000000..94b58a9 --- /dev/null +++ b/services/media_session/public/cpp/media_session.typemap
@@ -0,0 +1,22 @@ +# Copyright 2018 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. + +mojom = "//services/media_session/public/mojom/media_session.mojom" +public_headers = [ "//services/media_session/public/cpp/media_metadata.h" ] +traits_headers = + [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ] +public_deps = [ + "//services/media_session/public/cpp", +] +deps = [ + "//ui/gfx/geometry/mojo:struct_traits", +] +type_mappings = [ + "media_session.mojom.MediaImage=media_session::MediaMetadata::MediaImage", + "media_session.mojom.MediaMetadata=media_session::MediaMetadata", +] +sources = [ + "//services/media_session/public/cpp/media_session_mojom_traits.cc", + "//services/media_session/public/cpp/media_session_mojom_traits.h", +]
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.cc b/services/media_session/public/cpp/media_session_mojom_traits.cc new file mode 100644 index 0000000..067c7a2 --- /dev/null +++ b/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -0,0 +1,45 @@ +// Copyright 2018 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 "services/media_session/public/cpp/media_session_mojom_traits.h" + +#include "mojo/public/cpp/base/string16_mojom_traits.h" +#include "ui/gfx/geometry/mojo/geometry_struct_traits.h" +#include "url/mojom/url_gurl_mojom_traits.h" + +namespace mojo { + +// static +bool StructTraits<media_session::mojom::MediaImageDataView, + media_session::MediaMetadata::MediaImage>:: + Read(media_session::mojom::MediaImageDataView data, + media_session::MediaMetadata::MediaImage* out) { + if (!data.ReadSrc(&out->src)) + return false; + if (!data.ReadType(&out->type)) + return false; + if (!data.ReadSizes(&out->sizes)) + return false; + + return true; +} + +// static +bool StructTraits<media_session::mojom::MediaMetadataDataView, + media_session::MediaMetadata>:: + Read(media_session::mojom::MediaMetadataDataView data, + media_session::MediaMetadata* out) { + if (!data.ReadTitle(&out->title)) + return false; + if (!data.ReadArtist(&out->artist)) + return false; + if (!data.ReadAlbum(&out->album)) + return false; + if (!data.ReadArtwork(&out->artwork)) + return false; + + return true; +} + +} // namespace mojo
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.h b/services/media_session/public/cpp/media_session_mojom_traits.h new file mode 100644 index 0000000..b49dfa7 --- /dev/null +++ b/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -0,0 +1,63 @@ +// Copyright 2018 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_ +#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_ + +#include "services/media_session/public/mojom/media_session.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<media_session::mojom::MediaImageDataView, + media_session::MediaMetadata::MediaImage> { + static const GURL& src( + const media_session::MediaMetadata::MediaImage& image) { + return image.src; + } + + static const base::string16& type( + const media_session::MediaMetadata::MediaImage& image) { + return image.type; + } + + static const std::vector<gfx::Size>& sizes( + const media_session::MediaMetadata::MediaImage& image) { + return image.sizes; + } + + static bool Read(media_session::mojom::MediaImageDataView data, + media_session::MediaMetadata::MediaImage* out); +}; + +template <> +struct StructTraits<media_session::mojom::MediaMetadataDataView, + media_session::MediaMetadata> { + static const base::string16& title( + const media_session::MediaMetadata& metadata) { + return metadata.title; + } + + static const base::string16& artist( + const media_session::MediaMetadata& metadata) { + return metadata.artist; + } + + static const base::string16& album( + const media_session::MediaMetadata& metadata) { + return metadata.album; + } + + static const std::vector<media_session::MediaMetadata::MediaImage>& artwork( + const media_session::MediaMetadata& metadata) { + return metadata.artwork; + } + + static bool Read(media_session::mojom::MediaMetadataDataView data, + media_session::MediaMetadata* out); +}; + +} // namespace mojo + +#endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_
diff --git a/services/media_session/public/cpp/typemaps.gni b/services/media_session/public/cpp/typemaps.gni new file mode 100644 index 0000000..280e7e0 --- /dev/null +++ b/services/media_session/public/cpp/typemaps.gni
@@ -0,0 +1,5 @@ +# Copyright 2018 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. + +typemaps = [ "//services/media_session/public/cpp/media_session.typemap" ]
diff --git a/services/media_session/public/mojom/BUILD.gn b/services/media_session/public/mojom/BUILD.gn index 21d319d..fc5462b 100644 --- a/services/media_session/public/mojom/BUILD.gn +++ b/services/media_session/public/mojom/BUILD.gn
@@ -4,10 +4,7 @@ import("//mojo/public/tools/bindings/mojom.gni") -mojom_component("mojom") { - output_prefix = "media_session_public_mojom" - macro_prefix = "MEDIA_SESSION_PUBLIC_MOJOM" - +mojom("mojom") { sources = [ "audio_focus.mojom", "constants.mojom", @@ -17,5 +14,7 @@ public_deps = [ "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojo", + "//url/mojom:url_mojom_gurl", ] }
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom index e82b617..45ac627 100644 --- a/services/media_session/public/mojom/media_session.mojom +++ b/services/media_session/public/mojom/media_session.mojom
@@ -4,6 +4,10 @@ module media_session.mojom; +import "mojo/public/mojom/base/string16.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; +import "url/mojom/url.mojom"; + // Next MinVersion: 2 [Extensible] @@ -12,6 +16,23 @@ kPlaying, }; +// Album art in MediaMetadata +// Spec: https://wicg.github.io/mediasession/ +struct MediaImage { + url.mojom.Url src; + mojo_base.mojom.String16 type; + array<gfx.mojom.Size> sizes; +}; + +// MediaMetadata +// Spec: https://wicg.github.io/mediasession/ +struct MediaMetadata { + mojo_base.mojom.String16 title; + mojo_base.mojom.String16 artist; + mojo_base.mojom.String16 album; + array<MediaImage> artwork; +}; + // Contains state information about a MediaSession. struct MediaSessionInfo { [Extensible]
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index 114a212c..9baf1ec 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -35,6 +35,8 @@ "cross_origin_read_blocking.h", "data_pipe_element_reader.cc", "data_pipe_element_reader.h", + "dns_config_change_manager.cc", + "dns_config_change_manager.h", "empty_url_loader_client.cc", "empty_url_loader_client.h", "host_resolver.cc", @@ -270,6 +272,7 @@ "cors/preflight_controller_unittest.cc", "cross_origin_read_blocking_unittest.cc", "data_pipe_element_reader_unittest.cc", + "dns_config_change_manager_unittest.cc", "host_resolver_unittest.cc", "http_cache_data_counter_unittest.cc", "http_cache_data_remover_unittest.cc",
diff --git a/services/network/dns_config_change_manager.cc b/services/network/dns_config_change_manager.cc new file mode 100644 index 0000000..5a95b7a --- /dev/null +++ b/services/network/dns_config_change_manager.cc
@@ -0,0 +1,40 @@ +// Copyright 2018 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 "services/network/dns_config_change_manager.h" + +#include <utility> + +namespace network { + +DnsConfigChangeManager::DnsConfigChangeManager() { + net::NetworkChangeNotifier::AddDNSObserver(this); +} + +DnsConfigChangeManager::~DnsConfigChangeManager() { + net::NetworkChangeNotifier::RemoveDNSObserver(this); +} + +void DnsConfigChangeManager::AddBinding( + mojom::DnsConfigChangeManagerRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void DnsConfigChangeManager::RequestNotifications( + mojom::DnsConfigChangeManagerClientPtr client) { + clients_.AddPtr(std::move(client)); +} + +void DnsConfigChangeManager::OnDNSChanged() { + clients_.ForAllPtrs([](mojom::DnsConfigChangeManagerClient* client) { + client->OnSystemDnsConfigChanged(); + }); +} + +void DnsConfigChangeManager::OnInitialDNSConfigRead() { + // Service API makes no distinction between initial read and change. + OnDNSChanged(); +} + +} // namespace network
diff --git a/services/network/dns_config_change_manager.h b/services/network/dns_config_change_manager.h new file mode 100644 index 0000000..6d92f02f --- /dev/null +++ b/services/network/dns_config_change_manager.h
@@ -0,0 +1,46 @@ +// Copyright 2018 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 SERVICES_NETWORK_DNS_CONFIG_CHANGE_MANAGER_H_ +#define SERVICES_NETWORK_DNS_CONFIG_CHANGE_MANAGER_H_ + +#include <memory> +#include <set> + +#include "base/component_export.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "net/base/network_change_notifier.h" +#include "services/network/public/mojom/host_resolver.mojom.h" + +namespace network { + +class COMPONENT_EXPORT(NETWORK_SERVICE) DnsConfigChangeManager + : public mojom::DnsConfigChangeManager, + public net::NetworkChangeNotifier::DNSObserver { + public: + DnsConfigChangeManager(); + ~DnsConfigChangeManager() override; + + void AddBinding(mojom::DnsConfigChangeManagerRequest request); + + // mojom::DnsConfigChangeManager implementation: + void RequestNotifications( + mojom::DnsConfigChangeManagerClientPtr client) override; + + private: + // net::NetworkChangeNotifier::DNSObserver implementation: + void OnDNSChanged() override; + void OnInitialDNSConfigRead() override; + + mojo::BindingSet<mojom::DnsConfigChangeManager> bindings_; + mojo::InterfacePtrSet<mojom::DnsConfigChangeManagerClient> clients_; + + DISALLOW_COPY_AND_ASSIGN(DnsConfigChangeManager); +}; + +} // namespace network + +#endif // SERVICES_NETWORK_DNS_CONFIG_CHANGE_MANAGER_H_
diff --git a/services/network/dns_config_change_manager_unittest.cc b/services/network/dns_config_change_manager_unittest.cc new file mode 100644 index 0000000..5925cc54 --- /dev/null +++ b/services/network/dns_config_change_manager_unittest.cc
@@ -0,0 +1,126 @@ +// Copyright 2018 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 "services/network/dns_config_change_manager.h" + +#include <climits> +#include <utility> + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace network { +namespace { + +class TestDnsConfigChangeManagerClient + : public mojom::DnsConfigChangeManagerClient { + public: + explicit TestDnsConfigChangeManagerClient(DnsConfigChangeManager* manager) { + mojom::DnsConfigChangeManagerPtr manager_ptr; + mojom::DnsConfigChangeManagerRequest manager_request( + mojo::MakeRequest(&manager_ptr)); + manager->AddBinding(std::move(manager_request)); + + mojom::DnsConfigChangeManagerClientPtr client_ptr; + mojom::DnsConfigChangeManagerClientRequest client_request( + mojo::MakeRequest(&client_ptr)); + binding_.Bind(std::move(client_request)); + + manager_ptr->RequestNotifications(std::move(client_ptr)); + } + + void OnSystemDnsConfigChanged() override { + num_notifications_++; + if (num_notifications_ >= num_notifications_expected_) + run_loop_.Quit(); + } + + int num_notifications() { return num_notifications_; } + + void WaitForNotification(int num_notifications_expected) { + num_notifications_expected_ = num_notifications_expected; + if (num_notifications_ < num_notifications_expected_) + run_loop_.Run(); + } + + private: + int num_notifications_ = 0; + int num_notifications_expected_ = INT_MAX; + base::RunLoop run_loop_; + mojo::Binding<mojom::DnsConfigChangeManagerClient> binding_{this}; + + DISALLOW_COPY_AND_ASSIGN(TestDnsConfigChangeManagerClient); +}; + +class DnsConfigChangeManagerTest : public testing::Test { + public: + DnsConfigChangeManagerTest() {} + + DnsConfigChangeManager* manager() { return &manager_; } + TestDnsConfigChangeManagerClient* client() { return &client_; } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<net::NetworkChangeNotifier> notifier_mock_{ + net::NetworkChangeNotifier::CreateMock()}; + DnsConfigChangeManager manager_; + TestDnsConfigChangeManagerClient client_{&manager_}; + + DISALLOW_COPY_AND_ASSIGN(DnsConfigChangeManagerTest); +}; + +TEST_F(DnsConfigChangeManagerTest, Notification) { + EXPECT_EQ(0, client()->num_notifications()); + + net::NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests(); + client()->WaitForNotification(1); + EXPECT_EQ(1, client()->num_notifications()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, client()->num_notifications()); +} + +TEST_F(DnsConfigChangeManagerTest, Notification_InitialRead) { + EXPECT_EQ(0, client()->num_notifications()); + + net::NetworkChangeNotifier::NotifyObserversOfInitialDNSConfigReadForTests(); + client()->WaitForNotification(1); + EXPECT_EQ(1, client()->num_notifications()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, client()->num_notifications()); +} + +TEST_F(DnsConfigChangeManagerTest, MultipleNotification) { + EXPECT_EQ(0, client()->num_notifications()); + + net::NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests(); + net::NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests(); + client()->WaitForNotification(2); + EXPECT_EQ(2, client()->num_notifications()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, client()->num_notifications()); +} + +TEST_F(DnsConfigChangeManagerTest, MultipleClients) { + TestDnsConfigChangeManagerClient client2(manager()); + + EXPECT_EQ(0, client()->num_notifications()); + EXPECT_EQ(0, client2.num_notifications()); + + net::NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests(); + client()->WaitForNotification(1); + client2.WaitForNotification(1); + EXPECT_EQ(1, client()->num_notifications()); + EXPECT_EQ(1, client2.num_notifications()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, client()->num_notifications()); + EXPECT_EQ(1, client2.num_notifications()); +} + +} // namespace +} // namespace network
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 6296f0a..d59b9d9 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -2039,7 +2039,7 @@ #if defined(OS_CHROMEOS) void NetworkContext::TrustAnchorUsed() { - network_service_->client()->OnUsedTrustAnchor(params_->username_hash); + network_service_->client()->OnTrustAnchorUsed(params_->username_hash); } #endif
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index 225b9de..9acc02e 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -38,6 +38,7 @@ #include "net/url_request/url_request_context_builder.h" #include "services/network/crl_set_distributor.h" #include "services/network/cross_origin_read_blocking.h" +#include "services/network/dns_config_change_manager.h" #include "services/network/net_log_capture_mode_type_converter.h" #include "services/network/net_log_exporter.h" #include "services/network/network_context.h" @@ -197,6 +198,8 @@ network_quality_estimator_manager_ = std::make_unique<NetworkQualityEstimatorManager>(net_log_); + dns_config_change_manager_ = std::make_unique<DnsConfigChangeManager>(); + host_resolver_ = CreateHostResolver(net_log_); network_usage_accumulator_ = std::make_unique<NetworkUsageAccumulator>(); @@ -441,6 +444,11 @@ network_quality_estimator_manager_->AddRequest(std::move(request)); } +void NetworkService::GetDnsConfigChangeManager( + mojom::DnsConfigChangeManagerRequest request) { + dns_config_change_manager_->AddBinding(std::move(request)); +} + void NetworkService::GetTotalNetworkUsages( mojom::NetworkService::GetTotalNetworkUsagesCallback callback) { std::move(callback).Run(network_usage_accumulator_->GetTotalNetworkUsages());
diff --git a/services/network/network_service.h b/services/network/network_service.h index dea2f61..1d80691 100644 --- a/services/network/network_service.h +++ b/services/network/network_service.h
@@ -25,6 +25,7 @@ #include "services/network/network_change_manager.h" #include "services/network/network_quality_estimator_manager.h" #include "services/network/public/cpp/network_service_buildflags.h" +#include "services/network/public/mojom/host_resolver.mojom.h" #include "services/network/public/mojom/net_log.mojom.h" #include "services/network/public/mojom/network_change_manager.mojom.h" #include "services/network/public/mojom/network_quality_estimator_manager.mojom.h" @@ -51,6 +52,7 @@ namespace network { class CRLSetDistributor; +class DnsConfigChangeManager; class NetworkContext; class NetworkUsageAccumulator; class URLRequestContextBuilderMojo; @@ -147,6 +149,8 @@ mojom::NetworkChangeManagerRequest request) override; void GetNetworkQualityEstimatorManager( mojom::NetworkQualityEstimatorManagerRequest request) override; + void GetDnsConfigChangeManager( + mojom::DnsConfigChangeManagerRequest request) override; void GetTotalNetworkUsages( mojom::NetworkService::GetTotalNetworkUsagesCallback callback) override; #if BUILDFLAG(IS_CT_SUPPORTED) @@ -249,6 +253,8 @@ std::unique_ptr<NetworkQualityEstimatorManager> network_quality_estimator_manager_; + std::unique_ptr<DnsConfigChangeManager> dns_config_change_manager_; + std::unique_ptr<net::HostResolver> host_resolver_; std::unique_ptr<NetworkUsageAccumulator> network_usage_accumulator_;
diff --git a/services/network/network_service_unittest.cc b/services/network/network_service_unittest.cc index 7e6c486..e1788410 100644 --- a/services/network/network_service_unittest.cc +++ b/services/network/network_service_unittest.cc
@@ -1172,6 +1172,14 @@ EXPECT_TRUE(network_context.encountered_error()); } +TEST_F(NetworkServiceTestWithService, GetDnsConfigChangeManager) { + mojom::DnsConfigChangeManagerPtr ptr; + ASSERT_FALSE(ptr.is_bound()); + + network_service_->GetDnsConfigChangeManager(mojo::MakeRequest(&ptr)); + EXPECT_TRUE(ptr.is_bound()); +} + class TestNetworkChangeManagerClient : public mojom::NetworkChangeManagerClient { public:
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc index 10a89108..164bf1ad 100644 --- a/services/network/public/cpp/simple_url_loader.cc +++ b/services/network/public/cpp/simple_url_loader.cc
@@ -1226,11 +1226,18 @@ void SimpleURLLoaderImpl::SetOnRedirectCallback( const OnRedirectCallback& on_redirect_callback) { + // Check if a request has not yet been started. + DCHECK(!body_handler_); + on_redirect_callback_.push_back(on_redirect_callback); + DCHECK(on_redirect_callback); } void SimpleURLLoaderImpl::SetOnResponseStartedCallback( OnResponseStartedCallback on_response_started_callback) { + // Check if a request has not yet been started. + DCHECK(!body_handler_); + on_response_started_callback_ = std::move(on_response_started_callback); DCHECK(on_response_started_callback_); }
diff --git a/services/network/public/mojom/host_resolver.mojom b/services/network/public/mojom/host_resolver.mojom index 8bd8761..15dc9aa 100644 --- a/services/network/public/mojom/host_resolver.mojom +++ b/services/network/public/mojom/host_resolver.mojom
@@ -199,3 +199,17 @@ ResolveHostParameters? optional_parameters, ResolveHostClient response_client); }; + +// A client interface that subscribes to DNS config change events from +// DnsConfigChangeManager. +interface DnsConfigChangeManagerClient { + // Notifies that a potential change has been detected in the DNS settings of + // the system that may affect results of host resolution. + OnSystemDnsConfigChanged(); +}; + +// An interface that broadcasts DNS config change events. +interface DnsConfigChangeManager { + // Requests to receive notification when there is a DNS config change. + RequestNotifications(DnsConfigChangeManagerClient client_ptr); +};
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index 038838c..d65f1df 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom
@@ -104,8 +104,9 @@ bool fatal) => (int32 net_error); // Notification that a trust anchor was used for the given user. + // |username_hash| was the parameter passed in NetworkContextParams. [EnableIf=is_chromeos] - OnUsedTrustAnchor(string username_hash); + OnTrustAnchorUsed(string username_hash); // Called when file uploading was requested. // If the process that requested the uploads has permission to read all of @@ -294,6 +295,9 @@ GetNetworkQualityEstimatorManager( NetworkQualityEstimatorManager& network_quality_estimator_manager); + // Gets the DnsConfigChangeManager. + GetDnsConfigChangeManager(DnsConfigChangeManager& dns_config_change_manager); + // Gets the accumulated network usage since the start/restart of the service. GetTotalNetworkUsages() => (array<NetworkUsage> total_network_usages);
diff --git a/services/network/test/test_network_service_client.cc b/services/network/test/test_network_service_client.cc index 62be932..7a49d4a4 100644 --- a/services/network/test/test_network_service_client.cc +++ b/services/network/test/test_network_service_client.cc
@@ -80,7 +80,7 @@ } #if defined(OS_CHROMEOS) -void TestNetworkServiceClient::OnUsedTrustAnchor( +void TestNetworkServiceClient::OnTrustAnchorUsed( const std::string& username_hash) { NOTREACHED(); }
diff --git a/services/network/test/test_network_service_client.h b/services/network/test/test_network_service_client.h index de4148a..b658b838 100644 --- a/services/network/test/test_network_service_client.h +++ b/services/network/test/test_network_service_client.h
@@ -62,7 +62,7 @@ const net::CanonicalCookie& cookie, bool blocked_by_policy) override; #if defined(OS_CHROMEOS) - void OnUsedTrustAnchor(const std::string& username_hash) override; + void OnTrustAnchorUsed(const std::string& username_hash) override; #endif void OnFileUploadRequested(uint32_t process_id, bool async,
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index d7d4405..9bccaad 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -2212,7 +2212,7 @@ } #if defined(OS_CHROMEOS) - void OnUsedTrustAnchor(const std::string& username_hash) override { + void OnTrustAnchorUsed(const std::string& username_hash) override { NOTREACHED(); } #endif
diff --git a/services/ws/public/cpp/gpu/gpu.cc b/services/ws/public/cpp/gpu/gpu.cc index 8433f34..6854a88 100644 --- a/services/ws/public/cpp/gpu/gpu.cc +++ b/services/ws/public/cpp/gpu/gpu.cc
@@ -60,7 +60,7 @@ if (gpu_ptr_.encountered_error()) { ConnectionError(); } else { - gpu_ptr_->EstablishGpuChannel(base::BindRepeating( + gpu_ptr_->EstablishGpuChannel(base::BindOnce( &GpuPtrIO::OnEstablishedGpuChannel, base::Unretained(this))); } } @@ -188,7 +188,7 @@ establish_event_->Signal(); } else { main_task_runner_->PostTask( - FROM_HERE, base::Bind(&EstablishRequest::FinishOnMain, this)); + FROM_HERE, base::BindOnce(&EstablishRequest::FinishOnMain, this)); } } @@ -221,7 +221,7 @@ establish_request_->OnEstablishedGpuChannel( 0, mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(), gpu::GpuFeatureInfo()); - establish_request_ = nullptr; + establish_request_.reset(); } void Gpu::GpuPtrIO::OnEstablishedGpuChannel( @@ -235,7 +235,7 @@ establish_request_->OnEstablishedGpuChannel( client_id, std::move(channel_handle), std::move(gpu_info), std::move(gpu_feature_info)); - establish_request_ = nullptr; + establish_request_.reset(); } Gpu::Gpu(GpuPtrFactory factory, @@ -272,7 +272,7 @@ DCHECK(main_task_runner_->BelongsToCurrentThread()); if (pending_request_) { pending_request_->Cancel(); - pending_request_ = nullptr; + pending_request_.reset(); } if (gpu_channel_) @@ -373,14 +373,14 @@ DCHECK(main_task_runner_->BelongsToCurrentThread()); if (gpu_channel_) { gpu_channel_->DestroyChannel(); - gpu_channel_ = nullptr; + gpu_channel_.reset(); } } scoped_refptr<gpu::GpuChannelHost> Gpu::GetGpuChannel() { DCHECK(main_task_runner_->BelongsToCurrentThread()); if (gpu_channel_ && gpu_channel_->IsLost()) - gpu_channel_ = nullptr; + gpu_channel_.reset(); return gpu_channel_; } @@ -402,7 +402,7 @@ DCHECK(!gpu_channel_); gpu_channel_ = pending_request_->gpu_channel(); - pending_request_ = nullptr; + pending_request_.reset(); std::vector<gpu::GpuChannelEstablishedCallback> callbacks; callbacks.swap(establish_callbacks_);
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 5d93162b..32a3772 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -145,6 +145,10 @@ #define SK_USE_LEGACY_DISTANCE_FIELDS #endif +#ifndef SK_SUPPORT_LEGACY_NESTED_HINTINGENUM +#define SK_SUPPORT_LEGACY_NESTED_HINTINGENUM +#endif + // Skia is enabling this feature soon. Chrome probably does // not want it for M64 #ifndef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.content_browsertests.filter b/testing/buildbot/filters/chromeos.single_process_mash.content_browsertests.filter index c5f9a16d..c184647ef 100644 --- a/testing/buildbot/filters/chromeos.single_process_mash.content_browsertests.filter +++ b/testing/buildbot/filters/chromeos.single_process_mash.content_browsertests.filter
@@ -19,7 +19,6 @@ # or RenderWidgetHostMouseEventMonitor::EventWasReceived fails. # https://crbug.com/884360 -SitePerProcessHitTestBrowserTest.CrossProcessTooltipTest* --SitePerProcessHitTestBrowserTest.SubframeGestureEventRouting* # Flaky. https://crbug.com/889878
diff --git a/testing/libfuzzer/fuzzers/empty_fuzzer.cc b/testing/libfuzzer/fuzzers/empty_fuzzer.cc index fb38e802..2283518 100644 --- a/testing/libfuzzer/fuzzers/empty_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/empty_fuzzer.cc
@@ -7,12 +7,6 @@ #include <stddef.h> #include <stdint.h> -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - // Run your code on data. - return 0; -} - // Environment is optional. struct Environment { Environment() { @@ -20,6 +14,10 @@ } }; -Environment* env = new Environment(); - - +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // Initialize environment once. + static Environment env; + // Run your code on data. + return 0; +}
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 1bb16c50..743a97c 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -56,12 +56,13 @@ crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ] # New failures are appended below by the script. +crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ] crbug.com/864398 compositing/iframes/floating-self-painting-frame.html [ Failure ] crbug.com/591099 compositing/masks/mask-with-removed-filters.html [ Failure ] crbug.com/591099 compositing/video-frame-size-change.html [ Pass ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] -crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure ] +crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure Pass ] crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ] crbug.com/591099 external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html [ Failure ] crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Pass ] @@ -83,14 +84,16 @@ crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-011.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-003.html [ Pass ] +crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-005.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-003.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Pass ] crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ] +crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] -crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Pass ] crbug.com/591099 external/wpt/css/css-transitions/properties-value-implicit-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ] crbug.com/893550 external/wpt/css/css-ui/text-overflow-015.html [ Failure ] @@ -232,18 +235,18 @@ crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ] crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] crbug.com/591099 external/wpt/fetch/http-cache/basic-auth-cache-test.html [ Timeout ] -crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] +crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] crbug.com/591099 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ] +crbug.com/591099 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass ] crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Timeout ] -crbug.com/591099 external/wpt/html/dom/elements/the-innertext-idl-attribute/getter.html [ Failure ] crbug.com/591099 external/wpt/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html [ Timeout ] crbug.com/850504 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Failure ] crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Pass ] crbug.com/591099 external/wpt/picture-in-picture/leave-picture-in-picture.html [ Pass ] crbug.com/591099 external/wpt/picture-in-picture/picture-in-picture-window.html [ Pass ] crbug.com/591099 external/wpt/picture-in-picture/request-picture-in-picture-twice.html [ Pass ] -crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ] +crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass ] crbug.com/591099 external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Pass ] crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ] crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ] @@ -301,7 +304,6 @@ crbug.com/591099 http/tests/devtools/elements/shadow/shadow-distribution.js [ Failure ] crbug.com/591099 http/tests/devtools/network/network-datareceived.js [ Failure ] crbug.com/591099 http/tests/devtools/network/network-datasaver-warning.js [ Failure ] -crbug.com/591099 http/tests/devtools/persistence/persistence-merge-editor-tabs.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/service-workers/service-worker-v8-cache.js [ Pass ] crbug.com/591099 http/tests/images/feature-policy-unoptimized-images-cached-image.html [ Failure ] crbug.com/591099 http/tests/images/restyle-decode-error.html [ Failure ] @@ -312,13 +314,23 @@ crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] -crbug.com/591099 http/tests/webaudio/autoplay-crossorigin.html [ Failure ] -crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass ] +crbug.com/591099 http/tests/webaudio/autoplay-crossorigin.html [ Failure Timeout ] +crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass Timeout ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure ] crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure ] crbug.com/591099 intersection-observer/v2/text-shadow.html [ Failure ] +crbug.com/591099 media/controls-after-reload.html [ Failure ] +crbug.com/591099 media/controls-strict.html [ Failure ] +crbug.com/591099 media/controls-styling-strict.html [ Failure ] +crbug.com/591099 media/controls-styling.html [ Failure ] +crbug.com/591099 media/controls-without-preload.html [ Failure ] crbug.com/591099 media/controls/lazy-loaded-style.html [ Failure ] +crbug.com/591099 media/controls/paint-controls-webkit-appearance-none-custom-bg.html [ Failure ] +crbug.com/591099 media/controls/paint-controls-webkit-appearance-none.html [ Failure ] +crbug.com/591099 media/video-controls-rendering.html [ Failure ] +crbug.com/591099 media/video-display-toggle.html [ Failure ] +crbug.com/591099 media/video-no-audio.html [ Failure ] crbug.com/591099 paint/float/float-under-inline-self-painting-change.html [ Failure ] crbug.com/835484 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ] crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ] @@ -344,14 +356,14 @@ crbug.com/714962 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/position/relayout-fixed-position-after-scale.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint.html [ Pass Timeout ] +crbug.com/591099 paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint.html [ Pass ] crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ] crbug.com/591099 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/table/table-extra-bottom-grow.html [ Failure ] crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ] crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ] -crbug.com/591099 rootscroller/rootscroller-during-fullscreen.html [ Pass ] +crbug.com/591099 rootscroller/rootscroller-during-fullscreen.html [ Pass Timeout ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass ] crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] @@ -367,6 +379,7 @@ crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ] crbug.com/591099 transforms/3d/general/perspective-units.html [ Pass ] +crbug.com/591099 virtual/android/fullscreen/video-controls-timeline.html [ Failure ] crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure Pass ] crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Failure Pass ] crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ] @@ -375,7 +388,7 @@ crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] crbug.com/591099 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ] crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ] -crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/overflow-scrollability.html [ Crash Failure ] +crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/overflow-scrollability.html [ Failure Pass ] crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Pass Timeout ] @@ -391,6 +404,7 @@ crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] +crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Failure Pass ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/fetch/chromium/release-handle-crash.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] @@ -409,6 +423,7 @@ crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ] crbug.com/591099 virtual/scroll_customization/ [ Skip ] crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] +crbug.com/591099 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-registration-with-type.https.html [ Failure Pass ] crbug.com/591099 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html [ Pass ] crbug.com/591099 virtual/spv2/paint/invalidation/box/margin.html [ Failure Pass ] crbug.com/591099 virtual/stable/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 458212c..e2fc649 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2414,7 +2414,8 @@ crbug.com/665577 virtual/threaded/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Pass Timeout ] crbug.com/665577 [ Linux Win ] virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-interrupted.html [ Pass Failure Timeout ] -crbug.com/665577 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/track-scroll.html [ Pass Failure ] +# This test was [Pass Failure] on Mac and linked crbug.com/665577, lately it's also flakey on all 3 platforms: +crbug.com/901906 virtual/threaded/fast/scroll-behavior/smooth-scroll/track-scroll.html [ Pass Failure ] crbug.com/599670 [ Win ] http/tests/devtools/resource-parameters-ipv6.js [ Pass Failure Crash ] crbug.com/472330 fast/borders/border-image-outset-split-inline-vertical-lr.html [ Failure ] @@ -4185,6 +4186,9 @@ crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-anchors.html [ Skip ] crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-vertical-rl-anchors.html [ Skip ] +crbug.com/900431 [ Mac ] css3/blending/mix-blend-mode-isolated-group-1.html [ Pass Failure ] +crbug.com/900431 [ Mac ] css3/blending/mix-blend-mode-isolated-group-3.html [ Pass Failure ] + # ====== Random order flaky tests end here ====== # ====== Tests from enabling .any.js/.worker.js tests begin here ======
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/abspos/adjacent-to-relpos-inline-in-inline-that-had-block.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/abspos/adjacent-to-relpos-inline-in-inline-that-had-block.html new file mode 100644 index 0000000..1859ff8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/abspos/adjacent-to-relpos-inline-in-inline-that-had-block.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#containing-block-details"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level"> +<p>There should be a green square below, and no red.</p> +<div style="position:relative; width:100px; height:100px; background:red;"> + <span> + <span id="posMe"> + <div id="removeMe"></div> + </span> + </span> + <span> + <div> + <div id="target" style="position:absolute; width:100%; height:100%; background:green;"></div> + </div> + </span> +</div> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + test(()=> { + document.body.offsetTop; + removeMe.style.display = "none"; + document.body.offsetTop; + posMe.style.position = "relative"; + assert_equals(document.getElementById("target").offsetWidth, 100); + assert_equals(document.getElementById("target").offsetHeight, 100); + assert_equals(document.getElementById("target").offsetLeft, 0); + assert_equals(document.getElementById("target").offsetTop, 0); + }, "Make sure that we're sized by the right ancestor"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html new file mode 100644 index 0000000..b148df1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/feature-policy/resources/featurepolicy.js></script> + <!-- Feature-Policy: fullscreen cross_origin https://www.example.com; --> + <script> + 'use strict'; + var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}'; + var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}'; + var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html'; + var cross_origin_src = cross_origin + same_origin_src; + var header_policy = 'Feature-Policy: fullscreen \'self\' ' + cross_origin + + ' https://www.example.com;'; + + // Test that fullscreen's allowlist is [same_origin, cross_origin, 'https://www.example.com'] + test(function() { + assert_array_equals( + document.policy.getAllowlistForFeature('fullscreen'), + [cross_origin, 'https://www.example.com']); + }, header_policy + ' -- test allowlist is [cross_origin, https://www.example.com]'); + + // Test that fullscreen is disallowed on same_origin, allowed on some cross_origin subframes. + test_disallowed_feature_for_subframe( + header_policy + ' -- test fullscreen is allowed on same-origin subframe', + 'fullscreen', + same_origin_src); + test_allowed_feature_for_subframe( + header_policy + ' -- test fullscreen is allowed on cross-origin ' + cross_origin_src + ' subframe', + 'fullscreen', + cross_origin_src); + var cross_origin_src1 = 'https://{{domains[www1]}}:{{ports[https][0]}}' + same_origin_src; + test_disallowed_feature_for_subframe( + header_policy + ' -- test fullscreen is disallowed on cross-origin ' + cross_origin_src1 + ' subframe', + 'fullscreen', + cross_origin_src1); + + // dynamically update sub frame's container policy + var disallow = "fullscreen 'none';" + test_disallowed_feature_for_subframe( + header_policy + ', iframe.allow = ' + disallow + ' -- test fullscreen is disallowed on same-origin subframe', + 'fullscreen', + same_origin_src, + disallow); + + test_disallowed_feature_for_subframe( + header_policy + 'iframe.allow = ' + disallow + ' -- test fullscreen is allowed on specific cross-origin subframe', + 'fullscreen', + cross_origin_src, + disallow); + + var allow = "fullscreen " + cross_origin; + test_disallowed_feature_for_subframe( + header_policy + ', iframe.allow = ' + allow + ' -- test fullscreen is disallowed on same-origin subframe', + 'fullscreen', + same_origin_src, + allow); + + test_allowed_feature_for_subframe( + header_policy + 'iframe.allow = ' + allow + ' -- test fullscreen is allowed on specific cross-origin subframe', + 'fullscreen', + cross_origin_src, + allow); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html.sub.headers new file mode 100644 index 0000000..4ac2a4a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-header-policy-declined.https.sub.html.sub.headers
@@ -0,0 +1 @@ +Feature-Policy: fullscreen https://{{domains[www]}}:{{ports[https][0]}} https://www.example.com;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl index b79d09d..f00660bd 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/screen-capture.idl
@@ -3,7 +3,7 @@ // (https://github.com/tidoust/reffy-reports) // Source: Screen Capture (https://w3c.github.io/mediacapture-screen-share/) -partial interface Navigator { +partial interface MediaDevices { Promise<MediaStream> getDisplayMedia(optional MediaStreamConstraints constraints); };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt index d73ca783..dbf3a26 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt
@@ -3,7 +3,7 @@ PASS getDisplayMedia() with no constraints PASS getDisplayMedia() with video false PASS getDisplayMedia() with audio false -FAIL getDisplayMedia() with audio true promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getDisplayMedia' on 'Navigator': Audio capture is not supported" +FAIL getDisplayMedia() with audio true promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getDisplayMedia' on 'MediaDevices': Audio capture is not supported" PASS getDisplayMedia() with advanced constraint PASS getDisplayMedia() with min constraint PASS getDisplayMedia() with exact constraint
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html index 06ab72d2..36e0f22 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html
@@ -7,8 +7,8 @@ 'use strict'; promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia({video: true}); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia({video: true}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getTracks().length, 1); @@ -22,8 +22,8 @@ // Note that this results in some non-intuitive cases returning a video track, // i.e. {video: false}. promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia(); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia(); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getTracks().length, 1); @@ -32,8 +32,8 @@ }, 'getDisplayMedia() with no constraints'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia({video: false}); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia({video: false}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getTracks().length, 1); @@ -42,8 +42,8 @@ }, 'getDisplayMedia() with video false'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia({audio: false}); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia({audio: false}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getTracks().length, 1); @@ -52,8 +52,8 @@ }, 'getDisplayMedia() with audio false'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia({audio: true}); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia({audio: true}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getTracks().length, 1); @@ -62,10 +62,10 @@ }, 'getDisplayMedia() with audio true'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); try { - const stream = - await navigator.getDisplayMedia({video: {advanced: [{zoom: 1}]}}); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video: {advanced: [{zoom: 1}]}}); } catch (err) { assert_equals(err.name, 'TypeError'); return; @@ -74,10 +74,10 @@ }, 'getDisplayMedia() with advanced constraint'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); try { - const stream = - await navigator.getDisplayMedia({video: {width: {min: 360}}}); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video: {width: {min: 360}}}); } catch (err) { assert_equals(err.name, 'TypeError'); return; @@ -86,10 +86,10 @@ }, 'getDisplayMedia() with min constraint'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); try { - const stream = - await navigator.getDisplayMedia({video: {width: {exact: 360}}}); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video: {width: {exact: 360}}}); } catch (err) { assert_equals(err.name, 'TypeError'); return; @@ -98,10 +98,10 @@ }, 'getDisplayMedia() with exact constraint'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); const maxWidth = 360; - const stream = - await navigator.getDisplayMedia({video: {width: {max: maxWidth}}}); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video: {width: {max: maxWidth}}}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getVideoTracks().length, 1); @@ -111,10 +111,10 @@ }, 'getDisplayMedia() with max constraint'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); const maxWidth = 360; const maxFrameRate = 4; - const stream = await navigator.getDisplayMedia( + const stream = await navigator.mediaDevices.getDisplayMedia( {video: {width: {max: maxWidth}, frameRate: {max: maxFrameRate}}}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); @@ -126,9 +126,10 @@ }, 'getDisplayMedia() with constraints applied'); promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); try { - const stream = await navigator.getDisplayMedia({video: {width: {max: 0}}}); + const stream = await navigator.mediaDevices.getDisplayMedia( + {video: {width: {max: 0}}}); } catch (err) { assert_equals(err.name, 'OverconstrainedError'); return; @@ -138,8 +139,8 @@ // Content shell picks a fake desktop device by default. promise_test(async t => { - assert_idl_attribute(navigator, 'getDisplayMedia'); - const stream = await navigator.getDisplayMedia({video: true}); + assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia'); + const stream = await navigator.mediaDevices.getDisplayMedia({video: true}); const [track] = stream.getTracks(); t.add_cleanup(() => track.stop()); assert_equals(stream.getVideoTracks().length, 1);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/idlharness.window.js index 076e89f..527565e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/idlharness.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/idlharness.window.js
@@ -7,10 +7,10 @@ idl_test( ['screen-capture'], - ['mediacapture-streams', 'html'], + ['mediacapture-streams', 'html', 'dom'], idl_array => { idl_array.add_objects({ - Navigator: ['navigator'], + MediaDevices: ['navigator.mediaDevices'], }); } );
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/StyleSheet/gc-rule-children-wrappers-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/StyleSheet/gc-rule-children-wrappers-expected.txt index 74e5725..286ad88 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/StyleSheet/gc-rule-children-wrappers-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/StyleSheet/gc-rule-children-wrappers-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.styleSheets[0].cssRules[0].type is CSSRule.IMPORT_RULE PASS document.styleSheets[0].cssRules[0].media.foo is 'bar' PASS document.styleSheets[0].cssRules[0].type is CSSRule.IMPORT_RULE
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/gc-9-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/gc-9-expected.txt index 7082b613..792bed5 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/gc-9-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=HeapUnifiedGarbageCollection/fast/dom/gc-9-expected.txt
@@ -98,4 +98,3 @@ PASS: event.myCustomProperty should be 1 and is. DOM EVENT AFTER GARBAGE COLLECTION PASS: event.myCustomProperty should be 1 and is. -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding-expected.txt new file mode 100644 index 0000000..d1afa1cb --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding-expected.txt
@@ -0,0 +1,14 @@ +Verifies that html resources are previewed with the encoding set in their content-type header + +Running: testUTF8 +fetchScript: fetch('/devtools/network/resources/content-type-utf8.php') +iframe.src: data:text/html;charset=utf-8,utf8%20character:%20%E2%80%A6 + +Running: testISO +fetchScript: fetch('/devtools/network/resources/content-type-iso.php') +iframe.src: data:text/html;charset=iso-8859-1,iso-8859-1%20character:%20%C3%82%C2%A9 + +Running: testNoCharset +fetchScript: fetch('/devtools/network/resources/content-type-none.php') +iframe.src: data:text/html,no%20encoding +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding.js new file mode 100644 index 0000000..06f0bad4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/html-preview-encoding.js
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult( + 'Verifies that html resources are previewed with the encoding set in their content-type header'); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.showPanel('network'); + + async function runEncodingTest(url, nextTestCallback) { + const fetchScript = `fetch('${url}')`; + TestRunner.addResult('fetchScript: ' + fetchScript); + TestRunner.evaluateInPage(fetchScript); + + const request = await TestRunner.networkManager.once(SDK.NetworkManager.Events.RequestFinished); + + const previewView = new Network.RequestPreviewView(request); + previewView.wasShown(); + const htmlPreviewView = await previewView._contentViewPromise; + htmlPreviewView.wasShown(); + const iframe = htmlPreviewView.contentElement.firstChild; + TestRunner.addResult('iframe.src: ' + iframe.src); + + nextTestCallback(); + } + + TestRunner.runTestSuite([ + function testUTF8(next) { + runEncodingTest('/devtools/network/resources/content-type-utf8.php', next); + }, + function testISO(next) { + runEncodingTest('/devtools/network/resources/content-type-iso.php', next); + }, + function testNoCharset(next) { + runEncodingTest('/devtools/network/resources/content-type-none.php', next); + }, + ]); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-iso.php b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-iso.php new file mode 100644 index 0000000..29fd4e2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-iso.php
@@ -0,0 +1,4 @@ +<?php + header("content-type: text/html; charset=iso-8859-1;q=0.5"); + echo("iso-8859-1 character: ©"); +?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-none.php b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-none.php new file mode 100644 index 0000000..0c339a6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-none.php
@@ -0,0 +1,4 @@ +<?php + header_remove("Content-type"); + echo("no encoding"); +?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-utf8.php b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-utf8.php new file mode 100644 index 0000000..f76b07c --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/resources/content-type-utf8.php
@@ -0,0 +1,4 @@ +<?php + header("Content-Type: text/html; charset=utf-8"); + echo("utf8 character: …"); +?>
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index bbcdeb2..62c76e0 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4278,6 +4278,7 @@ getter ondevicechange method constructor method enumerateDevices + method getDisplayMedia method getSupportedConstraints method getUserMedia setter ondevicechange @@ -4719,7 +4720,6 @@ getter xr method constructor method getBattery - method getDisplayMedia method getGamepads method getInstalledRelatedApps method getUserMedia
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc index 4a413e46..2598e53 100644 --- a/third_party/blink/common/feature_policy/feature_policy.cc +++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -191,6 +191,10 @@ std::unique_ptr<FeaturePolicy> new_policy = base::WrapUnique(new FeaturePolicy(origin, features)); + // For features which are not keys in a container policy, which is the case + // here *until* we call AddContainerPolicy at the end of this method, + // https://wicg.github.io/feature-policy/#define-inherited-policy-in-container + // returns true if |feature| is enabled in |parent_policy| for |origin|. for (const auto& feature : features) { if (!parent_policy || parent_policy->IsFeatureEnabledForOrigin(feature.first, origin)) { @@ -208,11 +212,16 @@ const ParsedFeaturePolicy& container_policy, const FeaturePolicy* parent_policy) { DCHECK(parent_policy); + // For features which are keys in a container policy, + // https://wicg.github.io/feature-policy/#define-inherited-policy-in-container + // returns true only if |feature| is enabled in |parent| for either |origin| + // or |parent|'s origin, and the allowlist for |feature| matches |origin|. + // + // Roughly, If a feature is enabled in the parent frame, and the parent + // chooses to delegate it to the child frame, using the iframe attribute, then + // the feature should be enabled in the child frame. for (const ParsedFeaturePolicyDeclaration& parsed_declaration : container_policy) { - // If a feature is enabled in the parent frame, and the parent chooses to - // delegate it to the child frame, using the iframe attribute, then the - // feature should be enabled in the child frame. mojom::FeaturePolicyFeature feature = parsed_declaration.feature; // Do not allow setting a container policy for a feature which is not in the // feature list. @@ -220,21 +229,13 @@ if (search == inherited_policies_.end()) continue; bool& inherited_policy = search->second; - // If the parent frame does not enable the feature, then the child frame - // must not. - inherited_policy = false; - if (parent_policy->IsFeatureEnabled(feature)) { - if (parsed_declaration.matches_opaque_src && origin_.opaque()) { - // If the child frame has an opaque origin, and the declared container - // policy indicates that the feature should be enabled, enable it for - // the child frame. - inherited_policy = true; - } else if (AllowlistFromDeclaration(parsed_declaration) - ->Contains(origin_)) { - // Otherwise, enbable the feature if the declared container policy - // includes the origin of the child frame. - inherited_policy = true; - } + // If enabled by |parent_policy| for either |origin| or |parent_policy|'s + // origin, then enable in the child iff the declared container policy + // matches |origin|. + if (inherited_policy || parent_policy->IsFeatureEnabled(feature)) { + inherited_policy = + ((parsed_declaration.matches_opaque_src && origin_.opaque()) || + AllowlistFromDeclaration(parsed_declaration)->Contains(origin_)); } } }
diff --git a/third_party/blink/common/feature_policy/feature_policy_unittest.cc b/third_party/blink/common/feature_policy/feature_policy_unittest.cc index 591a217..7b30aec 100644 --- a/third_party/blink/common/feature_policy/feature_policy_unittest.cc +++ b/third_party/blink/common/feature_policy/feature_policy_unittest.cc
@@ -1023,6 +1023,98 @@ policy4->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_c_)); } +TEST_F(FeaturePolicyTest, TestFeatureDeclinedAtTopLevel) { + // +-----------------------------------------+ + // |(1)Origin A | + // |Feature-Policy: default-self 'none' | + // | | + // |<iframe allow="default-self OriginB"> | + // | +-------------------------------------+ | + // | |(2)Origin B | | + // | |No Policy | | + // | +-------------------------------------+ | + // | | + // |<iframe allow="default-self *"> | + // | +-------------------------------------+ | + // | |(3)Origin A | | + // | |No Policy | | + // | +-------------------------------------+ | + // +-----------------------------------------+ + // Default-self feature should be disabled in all frames. + std::unique_ptr<FeaturePolicy> policy1 = + CreateFromParentPolicy(nullptr, origin_a_); + policy1->SetHeaderPolicy( + {{{kDefaultSelfFeature, false, false, std::vector<url::Origin>()}}}); + ParsedFeaturePolicy frame_policy1 = { + {{kDefaultSelfFeature, false, false, {origin_b_}}}}; + std::unique_ptr<FeaturePolicy> policy2 = + CreateFromParentWithFramePolicy(policy1.get(), frame_policy1, origin_b_); + ParsedFeaturePolicy frame_policy2 = { + {{kDefaultSelfFeature, true, false, std::vector<url::Origin>()}}}; + std::unique_ptr<FeaturePolicy> policy3 = + CreateFromParentWithFramePolicy(policy1.get(), frame_policy2, origin_a_); + EXPECT_FALSE( + policy1->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_a_)); + EXPECT_FALSE( + policy2->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_b_)); + EXPECT_FALSE( + policy3->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_a_)); +} + +TEST_F(FeaturePolicyTest, TestFeatureDelegatedAndAllowed) { + // +-----------------------------------------+ + // |(1)Origin A | + // |Feature-Policy: default-self OriginB | + // | | + // |<iframe allow="default-self OriginA"> | + // | +-------------------------------------+ | + // | |(2)Origin B | | + // | |No Policy | | + // | +-------------------------------------+ | + // | | + // |<iframe allow="default-self OriginB"> | + // | +-------------------------------------+ | + // | |(3)Origin B | | + // | |No Policy | | + // | +-------------------------------------+ | + // | | + // |<iframe allow="default-self *"> | + // | +-------------------------------------+ | + // | |(4)Origin B | | + // | |No Policy | | + // | +-------------------------------------+ | + // +-----------------------------------------+ + // Default-self feature should be disabled in top-level frame and frame 2, and + // enabled in the remaining frames. + std::unique_ptr<FeaturePolicy> policy1 = + CreateFromParentPolicy(nullptr, origin_a_); + policy1->SetHeaderPolicy({{kDefaultSelfFeature, false, false, {origin_b_}}}); + ParsedFeaturePolicy frame_policy1 = { + {{kDefaultSelfFeature, false, false, {origin_a_}}}}; + std::unique_ptr<FeaturePolicy> policy2 = + CreateFromParentWithFramePolicy(policy1.get(), frame_policy1, origin_b_); + ParsedFeaturePolicy frame_policy2 = { + {{kDefaultSelfFeature, false, false, {origin_b_}}}}; + std::unique_ptr<FeaturePolicy> policy3 = + CreateFromParentWithFramePolicy(policy1.get(), frame_policy2, origin_b_); + ParsedFeaturePolicy frame_policy3 = { + {{kDefaultSelfFeature, true, false, std::vector<url::Origin>()}}}; + std::unique_ptr<FeaturePolicy> policy4 = + CreateFromParentWithFramePolicy(policy1.get(), frame_policy3, origin_b_); + EXPECT_FALSE( + policy1->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_a_)); + EXPECT_TRUE( + policy1->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_b_)); + EXPECT_FALSE( + policy2->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_a_)); + EXPECT_FALSE( + policy2->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_b_)); + EXPECT_TRUE( + policy3->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_b_)); + EXPECT_TRUE( + policy4->IsFeatureEnabledForOrigin(kDefaultSelfFeature, origin_b_)); +} + TEST_F(FeaturePolicyTest, TestDefaultSandboxedFramePolicy) { // +------------------+ // |(1)Origin A |
diff --git a/third_party/blink/public/platform/modules/background_sync/background_sync.mojom b/third_party/blink/public/platform/modules/background_sync/background_sync.mojom index 328eec0..b7b5288 100644 --- a/third_party/blink/public/platform/modules/background_sync/background_sync.mojom +++ b/third_party/blink/public/platform/modules/background_sync/background_sync.mojom
@@ -4,16 +4,8 @@ module blink.mojom; -enum BackgroundSyncNetworkState { - ANY, - AVOID_CELLULAR, - ONLINE, - MAX=ONLINE -}; - struct SyncRegistration { string tag = ""; - BackgroundSyncNetworkState network_state = ONLINE; }; enum BackgroundSyncError {
diff --git a/third_party/blink/renderer/build/scripts/make_names.py b/third_party/blink/renderer/build/scripts/make_names.py index d40a794a..3fcdf03 100755 --- a/third_party/blink/renderer/build/scripts/make_names.py +++ b/third_party/blink/renderer/build/scripts/make_names.py
@@ -37,15 +37,6 @@ import name_utilities -def _legacy_symbol(entry): - if entry['Symbol'] is not None: - return entry['Symbol'] - # FIXME: Remove this special case for the ugly x-webkit-foo attributes. - if entry['name'].original.startswith('-webkit-'): - return entry['name'].original.replace('-', '_')[1:] - return name_utilities.cpp_name(entry).replace('-', '_').replace(' ', '_') - - def _symbol(entry): if entry['Symbol'] is not None: return entry['Symbol'] @@ -70,7 +61,6 @@ filters = { 'cpp_name': name_utilities.cpp_name, 'hash': hasher.hash, - 'script_name': name_utilities.script_name, 'symbol': _symbol, } @@ -81,12 +71,13 @@ suffix = self.json5_file.metadata['suffix'].strip('"') export = self.json5_file.metadata['export'].strip('"') - assert namespace, 'A namespace is required.' - # TODO(tkent): Remove the following condition. Namespace fields of all - # foo_names.json5 should be lower-cased. crbug.com/889726 + if not namespace: + raise ValueError('A namespace is required.') + # https://google.github.io/styleguide/cppguide.html#Namespace_Names if namespace.lower() != namespace: - namespace = namespace + 'Names' - MakeNamesWriter.filters['symbol'] = _legacy_symbol + raise ValueError('The namespace field should be lower-cased. ' + + '"%s" is specified in %s.' % + (namespace, json5_file_path)) basename, _ = os.path.splitext(os.path.basename(json5_file_path[0])) self._outputs = {
diff --git a/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl index 2f6fd6c8..9d0a310 100644 --- a/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/make_names.cc.tmpl
@@ -10,16 +10,16 @@ namespace blink { namespace {{namespace}} { -void* {{suffix}}NamesStorage[k{{suffix}}NamesCount * ((sizeof(AtomicString) + sizeof(void *) - 1) / sizeof(void *))]; +void* {{suffix|lower}}names_storage[k{{suffix}}NamesCount * ((sizeof(AtomicString) + sizeof(void *) - 1) / sizeof(void *))]; {% for entry in entries|sort(attribute='name', case_sensitive=True) %} -const AtomicString& {{entry|symbol}} = reinterpret_cast<AtomicString*>(&{{suffix}}NamesStorage)[{{loop.index0}}]; +const AtomicString& {{entry|symbol}} = reinterpret_cast<AtomicString*>(&{{suffix|lower}}names_storage)[{{loop.index0}}]; {% endfor %} -void init{{suffix}}() { - static bool isLoaded = false; - if (isLoaded) return; - isLoaded = true; +void Init{{suffix}}() { + static bool is_loaded = false; + if (is_loaded) return; + is_loaded = true; struct NameEntry { const char* name; @@ -33,10 +33,10 @@ {% endfor %} }; - for (size_t i = 0; i < arraysize(kNames); i++) { - StringImpl* stringImpl = StringImpl::CreateStatic(kNames[i].name, kNames[i].length, kNames[i].hash); - void* address = reinterpret_cast<AtomicString*>(&{{suffix}}NamesStorage) + i; - new (address) AtomicString(stringImpl); + for (size_t i = 0; i < arraysize(kNames); ++i) { + StringImpl* impl = StringImpl::CreateStatic(kNames[i].name, kNames[i].length, kNames[i].hash); + void* address = reinterpret_cast<AtomicString*>(&{{suffix|lower}}names_storage) + i; + new (address) AtomicString(impl); } }
diff --git a/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl b/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl index 181a2f48..6b62497 100644 --- a/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl
@@ -25,7 +25,7 @@ constexpr unsigned k{{suffix}}NamesCount = {{entries|length}}; -{{symbol_export}}void init{{suffix}}(); +{{symbol_export}}void Init{{suffix}}(); } // namespace {{namespace}} } // namespace blink
diff --git a/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl index 12870ac..eacbbd4 100644 --- a/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl
@@ -13,59 +13,57 @@ namespace blink { namespace {{cpp_namespace}} { -using namespace blink; - DEFINE_GLOBAL(AtomicString, {{namespace_prefix}}NamespaceURI); {% if tags %} // Tags -void* {{suffix}}TagStorage[kTagsCount * ((sizeof({{namespace}}QualifiedName) + sizeof(void *) - 1) / sizeof(void *))]; +void* tag_storage[kTagsCount * ((sizeof({{namespace}}QualifiedName) + sizeof(void *) - 1) / sizeof(void *))]; {% for tag in tags|sort(attribute='name', case_sensitive=True) %} -const {{namespace}}QualifiedName& {{tag|symbol}}Tag = reinterpret_cast<{{namespace}}QualifiedName*>(&{{suffix}}TagStorage)[{{loop.index0}}]; +const {{namespace}}QualifiedName& {{tag|symbol}}Tag = reinterpret_cast<{{namespace}}QualifiedName*>(&tag_storage)[{{loop.index0}}]; {% endfor %} std::unique_ptr<const {{namespace}}QualifiedName*[]> GetTags() { auto tags = std::make_unique<const {{namespace}}QualifiedName*[]>(kTagsCount); - for (size_t i = 0; i < kTagsCount; i++) - tags[i] = reinterpret_cast<{{namespace}}QualifiedName*>(&{{suffix}}TagStorage) + i; + for (size_t i = 0; i < kTagsCount; ++i) + tags[i] = reinterpret_cast<{{namespace}}QualifiedName*>(&tag_storage) + i; return tags; } {% endif %} // Attributes -void* {{suffix}}AttrStorage[kAttrsCount * ((sizeof(QualifiedName) + sizeof(void *) - 1) / sizeof(void *))]; +void* attr_storage[kAttrsCount * ((sizeof(QualifiedName) + sizeof(void *) - 1) / sizeof(void *))]; {% for attr in attrs|sort(attribute='name', case_sensitive=True) %} -const QualifiedName& {{attr|symbol}}Attr = reinterpret_cast<QualifiedName*>(&{{suffix}}AttrStorage)[{{loop.index0}}]; +const QualifiedName& {{attr|symbol}}Attr = reinterpret_cast<QualifiedName*>(&attr_storage)[{{loop.index0}}]; {% endfor %} {% if namespace != 'HTML' %} std::unique_ptr<const QualifiedName*[]> GetAttrs() { auto attrs = std::make_unique<const QualifiedName*[]>(kAttrsCount); - for (size_t i = 0; i < kAttrsCount; i++) - attrs[i] = reinterpret_cast<QualifiedName*>(&{{suffix}}AttrStorage) + i; + for (size_t i = 0; i < kAttrsCount; ++i) + attrs[i] = reinterpret_cast<QualifiedName*>(&attr_storage) + i; return attrs; } {% endif %} -void init() { +void Init() { struct NameEntry { const char* name; unsigned hash; unsigned char length; - unsigned char isTag; - unsigned char isAttr; + unsigned char is_tag; + unsigned char is_attr; }; - // Use placement new to initialize the globals. - AtomicString {{namespace_prefix}}NS("{{namespace_uri}}"); - // Namespace - new ((void*)&{{namespace_prefix}}NamespaceURI) AtomicString({{namespace_prefix}}NS); + // Use placement new to initialize the globals. + AtomicString ns_uri("{{namespace_uri}}"); + new ((void*)&{{namespace_prefix}}NamespaceURI) AtomicString(ns_uri); + {% set tagnames = tags|map(attribute='name')|list() %} {% set attrnames = attrs|map(attribute='name')|list() %} static const NameEntry kNames[] = { @@ -78,25 +76,25 @@ size_t tag_i = 0; {% endif %} size_t attr_i = 0; - for (size_t i = 0; i < arraysize(kNames); i++) { - StringImpl* stringImpl = StringImpl::CreateStatic(kNames[i].name, kNames[i].length, kNames[i].hash); + for (size_t i = 0; i < arraysize(kNames); ++i) { + StringImpl* impl = StringImpl::CreateStatic(kNames[i].name, kNames[i].length, kNames[i].hash); {% if tags %} - if (kNames[i].isTag) { - void* address = reinterpret_cast<{{namespace}}QualifiedName*>(&{{suffix}}TagStorage) + tag_i; - QualifiedName::CreateStatic(address, stringImpl, {{namespace_prefix}}NS); - tag_i++; + if (kNames[i].is_tag) { + void* address = reinterpret_cast<{{namespace}}QualifiedName*>(&tag_storage) + tag_i; + QualifiedName::CreateStatic(address, impl, ns_uri); + ++tag_i; } - if (!kNames[i].isAttr) + if (!kNames[i].is_attr) continue; {% endif %} - void* address = reinterpret_cast<QualifiedName*>(&{{suffix}}AttrStorage) + attr_i; + void* address = reinterpret_cast<QualifiedName*>(&attr_storage) + attr_i; {% if use_namespace_for_attrs %} - QualifiedName::CreateStatic(address, stringImpl, {{namespace_prefix}}NS); + QualifiedName::CreateStatic(address, impl, ns_uri); {% else %} - QualifiedName::CreateStatic(address, stringImpl); + QualifiedName::CreateStatic(address, impl); {% endif %} - attr_i++; + ++attr_i; } {% if tags %} DCHECK_EQ(tag_i, kTagsCount);
diff --git a/third_party/blink/renderer/build/scripts/templates/make_qualified_names.h.tmpl b/third_party/blink/renderer/build/scripts/templates/make_qualified_names.h.tmpl index a1187e882..cb05c6c4 100644 --- a/third_party/blink/renderer/build/scripts/templates/make_qualified_names.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/make_qualified_names.h.tmpl
@@ -6,11 +6,12 @@ #ifndef {{header_guard}} #define {{header_guard}} +#include <memory> + {% if export == 'CORE_EXPORT' %} #include "third_party/blink/renderer/core/core_export.h" {% endif %} #include "third_party/blink/renderer/core/dom/qualified_name.h" -#include <memory> namespace blink { @@ -42,7 +43,7 @@ std::unique_ptr<const QualifiedName*[]> GetAttrs(); {% endif %} -void init(); +void Init(); } // namespace {{cpp_namespace}} } // namespace blink
diff --git a/third_party/blink/renderer/core/core_initializer.cc b/third_party/blink/renderer/core/core_initializer.cc index 16ce21f..850fade 100644 --- a/third_party/blink/renderer/core/core_initializer.cc +++ b/third_party/blink/renderer/core/core_initializer.cc
@@ -110,25 +110,25 @@ AtomicStringTable::Instance().ReserveCapacity(kCoreStaticStringsCount); - html_names::init(); - mathml_names::init(); - svg_names::init(); - xlink_names::init(); - xml_names::init(); - xmlns_names::init(); + html_names::Init(); + mathml_names::Init(); + svg_names::Init(); + xlink_names::Init(); + xml_names::Init(); + xmlns_names::Init(); - event_interface_names::init(); - event_target_names::init(); - event_type_names::init(); - fetch_initiator_type_names::init(); - font_family_names::init(); - html_tokenizer_names::init(); - http_names::init(); - input_mode_names::init(); - input_type_names::init(); - media_feature_names::init(); - media_type_names::init(); - performance_entry_names::init(); + event_interface_names::Init(); + event_target_names::Init(); + event_type_names::Init(); + fetch_initiator_type_names::Init(); + font_family_names::Init(); + html_tokenizer_names::Init(); + http_names::Init(); + input_mode_names::Init(); + input_type_names::Init(); + media_feature_names::Init(); + media_type_names::Init(); + performance_entry_names::Init(); MediaQueryEvaluator::Init(); CSSParserTokenRange::InitStaticEOFToken();
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 5e37307d..4c62e0d 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -332,8 +332,7 @@ should_dispatch_first_layout_after_finished_loading_(false), display_mode_(kWebDisplayModeBrowser), elastic_overscroll_(FloatSize()), - mutator_dispatcher_(nullptr), - override_compositor_visibility_(false) { + mutator_dispatcher_(nullptr) { DCHECK_EQ(!!client_, !!widget_client_); Page::PageClients page_clients; page_clients.chrome_client = chrome_client_.Get(); @@ -3323,21 +3322,27 @@ mojom::PageVisibilityState visibility_state, bool is_initial_state) { DCHECK(GetPage()); + const bool visible = visibility_state == mojom::PageVisibilityState::kVisible; + GetPage()->SetVisibilityState(visibility_state, is_initial_state); - bool visible = visibility_state == mojom::PageVisibilityState::kVisible; - if (layer_tree_view_ && !override_compositor_visibility_) - layer_tree_view_->SetVisible(visible); - GetPage()->GetPageScheduler()->SetPageVisible(visible); -} + // There is no frame yet during creation, but we set visibility on the page. + // The creator of the LayerTreeView is responsible for setting up its + // visibility. + if (GetPage()->MainFrame()) { + // The compositor for the main frame should be marked as visible or not only + // when the main frame is local. A remote main frame is not composited from + // this WebView, it would never be visible even if the Page is. + if (GetPage()->MainFrame()->IsLocalFrame()) { + // TODO(danakj): We shouldn't be changing visibility after closing, so why + // do we need to null check here - only for the DoDeferredClose case which + // does close out of order, starting with blink before IPCs are closed. + if (layer_tree_view_) + layer_tree_view_->SetVisible(visible); + } + } -void WebViewImpl::SetCompositorVisibility(bool is_visible) { - if (!is_visible) - override_compositor_visibility_ = true; - else - override_compositor_visibility_ = false; - if (layer_tree_view_) - layer_tree_view_->SetVisible(is_visible); + GetPage()->GetPageScheduler()->SetPageVisible(visible); } void WebViewImpl::ForceNextWebGLContextCreationToFail() {
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 55ae4d6..1fb3b12 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -464,10 +464,6 @@ float bottom_controls_height, bool browser_controls_shrink_layout); - // Overrides the compositor visibility. See the description of - // m_overrideCompositorVisibility for more details. - void SetCompositorVisibility(bool); - // TODO(lfg): Remove once WebViewFrameWidget is deleted. void ScheduleAnimationForWidget(); @@ -664,12 +660,6 @@ WebPageImportanceSignals page_importance_signals_; - // TODO(lfg): This is used in order to disable compositor visibility while - // the page is still visible. This is needed until the WebView and WebWidget - // split is complete, since in out-of-process iframes the page can be - // visible, but the WebView should not be used as a widget. - bool override_compositor_visibility_; - // We defer commits when transitioning to a new page. ChromeClientImpl calls // StopDeferringCommits() to release this when a new page is loaded. std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits_;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index 41899703..9d41326 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -19,13 +19,7 @@ WebViewFrameWidget::~WebViewFrameWidget() = default; void WebViewFrameWidget::Close() { - // Note: it's important to use the captured main frame pointer here. During - // a frame swap, the swapped frame is detached *after* the frame tree is - // updated. If the main frame is being swapped, then - // m_webView()->mainFrameImpl() will no longer point to the original frame. - web_view_->SetCompositorVisibility(false); web_view_ = nullptr; - WebFrameWidgetBase::Close(); // Note: this intentionally does not forward to WebView::close(), to make it @@ -181,9 +175,7 @@ return web_view_->ScrollFocusedEditableElementIntoView(); } -void WebViewFrameWidget::Initialize() { - web_view_->SetCompositorVisibility(true); -} +void WebViewFrameWidget::Initialize() {} void WebViewFrameWidget::SetLayerTreeView(WebLayerTreeView*) { // The WebViewImpl already has its LayerTreeView, the WebWidgetClient
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc index 71933f82..63c005c 100644 --- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc +++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
@@ -84,6 +84,7 @@ Platform::Current()->GetIOTaskRunner(); if (!parent_devtools_token_.is_empty() && io_task_runner) { // There may be no io task runner in unit tests. + wait_for_debugger_ = devtools_params->wait_for_debugger; agent_ = new DevToolsAgent(this, inspected_frames_.Get(), probe_sink_.Get(), std::move(inspector_task_runner), std::move(io_task_runner)); @@ -146,6 +147,13 @@ agent_->FlushProtocolNotifications(); } +void WorkerInspectorController::WaitForDebuggerIfNeeded() { + if (!wait_for_debugger_) + return; + wait_for_debugger_ = false; + debugger_->PauseWorkerOnStart(thread_); +} + void WorkerInspectorController::WillProcessTask( const base::PendingTask& pending_task) {}
diff --git a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h index c11fa715..063bb4a 100644 --- a/third_party/blink/renderer/core/inspector/worker_inspector_controller.h +++ b/third_party/blink/renderer/core/inspector/worker_inspector_controller.h
@@ -69,6 +69,7 @@ DevToolsAgent* GetDevToolsAgent() const { return agent_.Get(); } void Dispose(); void FlushProtocolNotifications(); + void WaitForDebuggerIfNeeded(); private: WorkerInspectorController(WorkerThread*, @@ -99,6 +100,7 @@ Member<InspectedFrames> inspected_frames_; Member<CoreProbeSink> probe_sink_; int session_count_ = 0; + bool wait_for_debugger_ = false; // These fields are set up in the constructor and then read // on a random thread from EmitTraceEvent().
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index 5b0c177..c253362 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -231,25 +231,50 @@ // to pass its style on to anyone else. const ComputedStyle& new_style = StyleRef(); if (LayoutInline* continuation = InlineElementContinuation()) { + bool position_type_changed = + old_style && (new_style.GetPosition() != old_style->GetPosition()) && + (new_style.HasInFlowPosition() || old_style->HasInFlowPosition()); + + // An inline that establishes a continuation is normally wrapped inside an + // anonymous block, of course, but if the continuation chain has been + // partially torn down (read comment further below), this is not the + // case. Here we want to find the nearest containing block that's an + // ancestor of all the continuations. + const LayoutBlock* boundary = ContainingBlock(); + if (boundary->IsAnonymousBlock()) + boundary = boundary->ContainingBlock(); LayoutInline* previous_part = this; LayoutInline* end_of_continuation = nullptr; - bool is_real_continuation = false; + bool needs_anon_block_position_update = false; for (LayoutInline* curr_cont = continuation; curr_cont; curr_cont = curr_cont->InlineElementContinuation()) { - if (!is_real_continuation && curr_cont != previous_part->NextSibling()) { + if (position_type_changed && !needs_anon_block_position_update) { // When we have a continuation chain, and the block child that was the // reason for creating that in the first place is removed, we don't // clean up the continuation chain. Previously split inlines should // ideally be joined when this happens, but we don't do that, but rather - // leave the mess around. We'll end up with direct LayoutInline siblings - // for the same Node (that form a bogus continuation chain). Here we - // check that we're NOT in such a situation, and that the Node actually - // forms a real continuation chain. This matters when it comes to - // marking the anonymous container(s) of block children as relatively - // positioned. We should only do that if the Node is an ancestor of the + // leave the mess around. We'll end up with LayoutInline siblings or + // cousins for the same Node (that form a bogus continuation chain), + // without any blocks in-between. Here we check that we're NOT in such a + // situation, and that the Node actually forms a real continuation + // chain. This matters when it comes to marking the anonymous + // container(s) of block children as relatively positioned (further + // below). We should only do that if the Node is an ancestor of the // blocks. Otherwise out-of-flow positioned descendants will use the // wrong containing block. - is_real_continuation = true; + for (LayoutObject* walker = previous_part->NextInPreOrder(boundary); + walker;) { + if (walker == curr_cont) + break; + if (walker->IsAnonymousBlock()) { + needs_anon_block_position_update = true; + break; + } + if (walker->IsLayoutInline()) + walker = walker->NextInPreOrder(boundary); + else + walker = walker->NextInPreOrderAfterChildren(boundary); + } } previous_part = curr_cont; @@ -260,14 +285,13 @@ end_of_continuation = curr_cont; } - if (is_real_continuation && old_style) { + if (needs_anon_block_position_update) { + DCHECK(old_style); DCHECK(end_of_continuation); LayoutObject* block = ContainingBlock()->NextSibling(); // If an inline's in-flow positioning has changed then any descendant // blocks will need to change their styles accordingly. - if (block && block->IsAnonymousBlock() && - new_style.GetPosition() != old_style->GetPosition() && - (new_style.HasInFlowPosition() || old_style->HasInFlowPosition())) { + if (block && block->IsAnonymousBlock()) { UpdateInFlowPositionOfAnonymousBlockContinuations( block, new_style, *old_style, end_of_continuation->ContainingBlock());
diff --git a/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.cc b/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.cc index b335ff8a..9dc7146 100644 --- a/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.cc +++ b/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.cc
@@ -48,47 +48,6 @@ } } -NGPhysicalOffset NGPhysicalOffset::operator+( - const NGPhysicalOffset& other) const { - return NGPhysicalOffset{this->left + other.left, this->top + other.top}; -} - -NGPhysicalOffset& NGPhysicalOffset::operator+=(const NGPhysicalOffset& other) { - *this = *this + other; - return *this; -} - -NGPhysicalOffset NGPhysicalOffset::operator-( - const NGPhysicalOffset& other) const { - return NGPhysicalOffset{this->left - other.left, this->top - other.top}; -} - -NGPhysicalOffset& NGPhysicalOffset::operator-=(const NGPhysicalOffset& other) { - *this = *this - other; - return *this; -} - -bool NGPhysicalOffset::operator==(const NGPhysicalOffset& other) const { - return other.left == left && other.top == top; -} - -NGPhysicalOffset::NGPhysicalOffset(const LayoutPoint& point) { - left = point.X(); - top = point.Y(); -} -NGPhysicalOffset::NGPhysicalOffset(const LayoutSize& size) { - left = size.Width(); - top = size.Height(); -} - -LayoutPoint NGPhysicalOffset::ToLayoutPoint() const { - return {left, top}; -} - -LayoutSize NGPhysicalOffset::ToLayoutSize() const { - return {left, top}; -} - String NGPhysicalOffset::ToString() const { return String::Format("%d,%d", left.ToInt(), top.ToInt()); }
diff --git a/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h b/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h index 8acb4de..4295353b 100644 --- a/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h +++ b/third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h
@@ -6,6 +6,8 @@ #define NGPhysicalOffset_h #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/geometry/layout_point.h" +#include "third_party/blink/renderer/platform/geometry/layout_size.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/text/writing_mode.h" @@ -35,23 +37,41 @@ NGPhysicalSize outer_size, NGPhysicalSize inner_size) const; - NGPhysicalOffset operator+(const NGPhysicalOffset& other) const; - NGPhysicalOffset& operator+=(const NGPhysicalOffset& other); + NGPhysicalOffset operator+(const NGPhysicalOffset& other) const { + return NGPhysicalOffset{this->left + other.left, this->top + other.top}; + } + NGPhysicalOffset& operator+=(const NGPhysicalOffset& other) { + *this = *this + other; + return *this; + } - NGPhysicalOffset operator-(const NGPhysicalOffset& other) const; - NGPhysicalOffset& operator-=(const NGPhysicalOffset& other); + NGPhysicalOffset operator-(const NGPhysicalOffset& other) const { + return NGPhysicalOffset{this->left - other.left, this->top - other.top}; + } + NGPhysicalOffset& operator-=(const NGPhysicalOffset& other) { + *this = *this - other; + return *this; + } - bool operator==(const NGPhysicalOffset& other) const; + bool operator==(const NGPhysicalOffset& other) const { + return other.left == left && other.top == top; + } // Conversions from/to existing code. New code prefers type safety for // logical/physical distinctions. - explicit NGPhysicalOffset(const LayoutPoint& point); - explicit NGPhysicalOffset(const LayoutSize& size); + explicit NGPhysicalOffset(const LayoutPoint& point) { + left = point.X(); + top = point.Y(); + } + explicit NGPhysicalOffset(const LayoutSize& size) { + left = size.Width(); + top = size.Height(); + } // Conversions from/to existing code. New code prefers type safety for // logical/physical distinctions. - LayoutPoint ToLayoutPoint() const; - LayoutSize ToLayoutSize() const; + LayoutPoint ToLayoutPoint() const { return {left, top}; } + LayoutSize ToLayoutSize() const { return {left, top}; } String ToString() const; };
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc index 3b6df7f..43dfe5e 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -729,15 +729,26 @@ for (LayoutObject* layout_object = block_flow->NextInPreOrder(block_flow); layout_object;) { bool should_dirty_lines = false; + NGPaintFragment* fragment = nullptr; LayoutObject* next = nullptr; - if (layout_object->IsText()) { - should_dirty_lines = - !has_dirtied_lines && layout_object->SelfNeedsLayout(); + if (LayoutText* layout_text = ToLayoutTextOrNull(layout_object)) { + if (!has_dirtied_lines) { + should_dirty_lines = layout_object->SelfNeedsLayout(); + if (!should_dirty_lines) + fragment = layout_text->FirstInlineFragment(); + } next = layout_object->NextInPreOrderAfterChildren(block_flow); layout_object->ClearNeedsLayout(); - } else if (layout_object->IsLayoutInline()) { - should_dirty_lines = - !has_dirtied_lines && layout_object->SelfNeedsLayout(); + } else if (LayoutInline* layout_inline = + ToLayoutInlineOrNull(layout_object)) { + if (!has_dirtied_lines) { + should_dirty_lines = layout_object->SelfNeedsLayout(); + // Do not keep fragments of LayoutInline unless it's a leaf, because + // the last fragment of LayoutInline is not the previous fragment of its + // descendants. + if (!should_dirty_lines && !layout_inline->FirstChild()) + fragment = layout_inline->FirstInlineFragment(); + } next = layout_object->NextInPreOrder(block_flow); layout_object->ClearNeedsLayout(); } else if (UNLIKELY(layout_object->IsFloatingOrOutOfFlowPositioned())) { @@ -751,7 +762,11 @@ // solution if any. return false; } else if (layout_object->IsAtomicInlineLevel()) { - should_dirty_lines = !has_dirtied_lines && layout_object->NeedsLayout(); + if (!has_dirtied_lines) { + should_dirty_lines = layout_object->NeedsLayout(); + if (!should_dirty_lines) + fragment = layout_object->FirstInlineFragment(); + } next = layout_object->NextInPreOrderAfterChildren(block_flow); } else { NOTREACHED(); @@ -778,9 +793,8 @@ first_line->MarkLineBoxDirty(); } has_dirtied_lines = true; - } else { - if (NGPaintFragment* fragment = layout_object->FirstInlineFragment()) - last_fragment = fragment; + } else if (fragment) { + last_fragment = fragment; } }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc index 282c5ff..bd106cb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -830,4 +830,25 @@ EXPECT_TRUE(lines[1]->IsDirty()); } +// Test marking line boxes when a span inside a span has NeedsLayout. +// The parent span has a box fragment, and wraps, so that its fragment +// is seen earlier in pre-order DFS. +TEST_F(NGInlineNodeTest, MarkLineBoxesDirtyOnChildOfWrappedBox) { + SetupHtml("container", R"HTML( + <div id=container style="font-size: 10px"> + <span style="background: yellow"> + <span id=t>target</span> + <br> + 12345678 + </span> + </div> + )HTML"); + + LayoutObject* span = GetLayoutObjectByElementId("t"); + span->SetNeedsLayout(""); + + auto lines = MarkLineBoxesDirty(); + EXPECT_TRUE(lines[0]->IsDirty()); +} + } // namespace blink
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 75bc75b..d3130ea 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
@@ -103,8 +103,7 @@ if (!has_processed_first_child) { // The offset of the flow thread should be the same as that of the first // first column. - flow_thread->SetX(child.Offset().left); - flow_thread->SetY(child.Offset().top); + flow_thread->SetLocation(child.Offset().ToLayoutPoint()); flow_thread->SetLogicalWidth(child_fragment.InlineSize()); column_block_size = child_fragment.BlockSize(); has_processed_first_child = true; @@ -510,7 +509,7 @@ const NGConstraintSpace& constraint_space, const NGLayoutResult& layout_result) { DCHECK(layout_result.PhysicalFragment()); - if (constraint_space.IsIntermediateLayout()) + if (UNLIKELY(constraint_space.IsIntermediateLayout())) return; const NGPhysicalBoxFragment& physical_fragment = @@ -527,7 +526,7 @@ // legacy layout doesn't support non-uniform fragmentainer widths. LayoutUnit logical_height; LayoutUnit intrinsic_content_logical_height; - if (IsFirstFragment(constraint_space, physical_fragment)) { + if (LIKELY(IsFirstFragment(constraint_space, physical_fragment))) { box_->SetLogicalWidth(fragment_logical_size.inline_size); } else { DCHECK_EQ(box_->LogicalWidth(), fragment_logical_size.inline_size) @@ -547,7 +546,7 @@ NGBoxStrut padding = fragment.Padding(); NGBoxStrut border_scrollbar_padding = borders + scrollbars + padding; - if (IsLastFragment(physical_fragment)) + if (LIKELY(IsLastFragment(physical_fragment))) intrinsic_content_logical_height -= border_scrollbar_padding.BlockSum(); box_->SetLogicalHeight(logical_height); box_->SetIntrinsicContentLogicalHeight(intrinsic_content_logical_height); @@ -557,11 +556,11 @@ box_->SetMargin(ComputePhysicalMargins(constraint_space, Style())); LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(*box_); - if (flow_thread) { + if (UNLIKELY(flow_thread)) { PlaceChildrenInFlowThread(constraint_space, physical_fragment); } else { NGPhysicalOffset offset_from_start; - if (constraint_space.HasBlockFragmentation()) { + if (UNLIKELY(constraint_space.HasBlockFragmentation())) { // Need to include any block space that this container has used in // previous fragmentainers. The offset of children will be relative to // the container, in flow thread coordinates, i.e. the model where @@ -576,16 +575,17 @@ offset_from_start); } - if (box_->IsLayoutBlock() && IsLastFragment(physical_fragment)) { - LayoutBlock* block = ToLayoutBlock(box_); + LayoutBlock* block = ToLayoutBlockOrNull(box_); + if (LIKELY(block && IsLastFragment(physical_fragment))) { LayoutUnit intrinsic_block_size = layout_result.IntrinsicBlockSize(); - if (constraint_space.HasBlockFragmentation()) { + if (UNLIKELY(constraint_space.HasBlockFragmentation())) { intrinsic_block_size += PreviouslyUsedBlockSpace(constraint_space, physical_fragment); } - block->LayoutPositionedObjects(/* relayout_children */ false); + if (UNLIKELY(block->HasPositionedObjects())) + block->LayoutPositionedObjects(/* relayout_children */ false); - if (flow_thread) { + if (UNLIKELY(flow_thread)) { UpdateLegacyMultiColumnFlowThread(*this, flow_thread, constraint_space, physical_fragment); } @@ -600,10 +600,9 @@ box_->ClearNeedsLayout(); // Overflow computation depends on this being set. - if (box_->IsLayoutBlockFlow()) { - LayoutBlockFlow* block_flow = ToLayoutBlockFlow(box_); + LayoutBlockFlow* block_flow = ToLayoutBlockFlowOrNull(box_); + if (LIKELY(block_flow)) block_flow->UpdateIsSelfCollapsing(); - } } void NGBlockNode::PlaceChildrenInLayoutBox( @@ -701,8 +700,8 @@ horizontal_offset = containing_block->Size().Width() - horizontal_offset - fragment.Size().width; } - layout_box->SetX(horizontal_offset); - layout_box->SetY(fragment_offset.top + additional_offset.top); + layout_box->SetLocation(LayoutPoint( + horizontal_offset, fragment_offset.top + additional_offset.top)); // Floats need an associated FloatingObject for painting. if (IsFloatFragment(fragment) && containing_block->IsLayoutBlockFlow()) {
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index 78f2846..04e6684 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -269,12 +269,12 @@ } std::unique_ptr<ImageRecord> record = std::make_unique<ImageRecord>(); record->node_id = node_id; - record->first_size = rect_size; - record->first_paint_index = ++first_paint_index_max_; record->image_url = !cachedImg ? "" : cachedImg->Url().StrippedForUseAsReferrer(); + // Mind that first_size has to be assigned at the push of + // largest_image_heap_ since it's the sorting key. + record->first_size = rect_size; largest_image_heap_.push(record->AsWeakPtr()); - latest_image_heap_.push(record->AsWeakPtr()); id_record_map_.insert(node_id, std::move(record)); } else { // for assessing whether kImageNodeNumberLimit is large enough for all @@ -288,8 +288,17 @@ if (id_record_map_.Contains(node_id) && IsJustLoaded(cachedImg, *id_record_map_.at(node_id))) { records_pending_timing_.push(node_id); - id_record_map_.at(node_id)->frame_index = frame_index_; - id_record_map_.at(node_id)->loaded = true; + ImageRecord* record = id_record_map_.at(node_id); + record->frame_index = frame_index_; + record->loaded = true; + // Latest image heap differs from largest image heap in that the former + // pushes a record when an image is loaded while the latter pushes when an + // image is attached to DOM. This causes last image paint to base its order + // on load time other than attachment time. + // Mind that first_paint_index has to be assigned at the push of + // latest_image_heap_ since it's the sorting key. + record->first_paint_index = ++first_paint_index_max_; + latest_image_heap_.push(record->AsWeakPtr()); } }
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc index 3f11b3c..34630a1 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" +#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkSurface.h" @@ -313,41 +314,81 @@ } TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_Last) { + WTF::ScopedMockClock clock; SetBodyInnerHTML(R"HTML( <div id="parent"> - <img id="1"></img> - <img id="2"></img> - <img id="3"></img> + <img height="10" width="10" id="1"></img> + <img height="5" width="5" id="2"></img> + <img height="7" width="7" id="3"></img> </div> )HTML"); - TimeTicks time1 = CurrentTimeTicks(); + GetFrameView().UpdateAllLifecyclePhases(); SetImageAndPaint("1", 10, 10); - UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + GetFrameView().UpdateAllLifecyclePhases(); + clock.Advance(TimeDelta::FromSecondsD(1)); + InvokeCallback(); + ImageRecord* record; record = FindLastPaintCandidate(); EXPECT_TRUE(record); - EXPECT_GE(record->first_paint_time_after_loaded, time1); + EXPECT_EQ(record->first_size, 100); + EXPECT_EQ(record->first_paint_time_after_loaded, + base::TimeTicks() + TimeDelta::FromSecondsD(1)); - TimeTicks time2 = CurrentTimeTicks(); SetImageAndPaint("2", 5, 5); - UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); - record = FindLastPaintCandidate(); - EXPECT_TRUE(record); - EXPECT_GE(record->first_paint_time_after_loaded, time2); + GetFrameView().UpdateAllLifecyclePhases(); + clock.Advance(TimeDelta::FromSecondsD(1)); + InvokeCallback(); - TimeTicks time3 = CurrentTimeTicks(); - SetImageAndPaint("3", 7, 7); - UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); record = FindLastPaintCandidate(); EXPECT_TRUE(record); - EXPECT_GE(record->first_paint_time_after_loaded, time3); +#if defined(OS_MACOSX) + EXPECT_EQ(record->first_size, 30); +#else + EXPECT_EQ(record->first_size, 25); +#endif + EXPECT_EQ(record->first_paint_time_after_loaded, + base::TimeTicks() + TimeDelta::FromSecondsD(2)); + + SetImageAndPaint("3", 7, 7); + GetFrameView().UpdateAllLifecyclePhases(); + clock.Advance(TimeDelta::FromSecondsD(1)); + // 6th s + InvokeCallback(); + record = FindLastPaintCandidate(); + EXPECT_TRUE(record); + EXPECT_GE(record->first_paint_time_after_loaded, + base::TimeTicks() + TimeDelta::FromSecondsD(3)); GetDocument().getElementById("parent")->RemoveChild( GetDocument().getElementById("3")); record = FindLastPaintCandidate(); EXPECT_TRUE(record); - EXPECT_GE(record->first_paint_time_after_loaded, time2); - EXPECT_LE(record->first_paint_time_after_loaded, time3); + EXPECT_GE(record->first_paint_time_after_loaded, + base::TimeTicks() + TimeDelta::FromSecondsD(2)); +} + +TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_LastBasedOnLoadTime) { + SetBodyInnerHTML(R"HTML( + <div id="parent"> + <img height="5" width="5" id="1"></img> + </div> + )HTML"); + Element* image = GetDocument().CreateRawElement(html_names::kImgTag); + image->setAttribute(html_names::kIdAttr, "2"); + image->setAttribute(html_names::kHeightAttr, "10"); + image->setAttribute(html_names::kWidthAttr, "10"); + GetDocument().getElementById("parent")->appendChild(image); + SetImageAndPaint("2", 10, 10); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + + SetImageAndPaint("1", 5, 5); + UpdateAllLifecyclePhasesAndInvokeCallbackIfAny(); + + ImageRecord* record; + record = FindLastPaintCandidate(); + EXPECT_TRUE(record); + EXPECT_EQ(record->first_size, 25); } TEST_F(ImagePaintTimingDetectorTest, LastImagePaint_IgnoreTheRemoved) {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index 8ddd558..dd590a88 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -601,9 +601,6 @@ void NGPaintFragment::MarkLineBoxesDirtyFor(const LayoutObject& layout_object) { DCHECK(layout_object.IsInline()) << layout_object; - if (TryMarkFirstLineBoxDirtyFor(layout_object)) - return; - // Since |layout_object| isn't in fragment tree, check preceding siblings. // Note: Once we reuse lines below dirty lines, we should check next siblings. for (LayoutObject* previous = layout_object.PreviousSibling(); previous;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc index 334a0ce..210e85d 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
@@ -584,9 +584,10 @@ Element& target = *GetDocument().getElementById("target"); ToText(*target.firstChild()).setData("abc"); const NGPaintFragment& container = *GetPaintFragmentByElementId("container"); - EXPECT_FALSE(container.FirstChild()->IsDirty()); - EXPECT_TRUE(ToList(container.Children())[1]->IsDirty()); - EXPECT_FALSE(ToList(container.Children())[2]->IsDirty()); + auto lines = ToList(container.Children()); + // TODO(kojii): Currently we don't optimzie for <br>. We can do this, then + // lines[0] should not be dirty. + EXPECT_TRUE(lines[0]->IsDirty()); } TEST_F(NGPaintFragmentTest, MarkLineBoxesDirtyWrappedLine) {
diff --git a/third_party/blink/renderer/core/workers/experimental/task.cc b/third_party/blink/renderer/core/workers/experimental/task.cc index 9f5ac38a..ad2ef3ec 100644 --- a/third_party/blink/renderer/core/workers/experimental/task.cc +++ b/third_party/blink/renderer/core/workers/experimental/task.cc
@@ -17,10 +17,11 @@ namespace blink { -class ThreadPoolTask::AsyncFunctionCompleted : public ScriptFunction { +// worker_thread_ only. +class Task::AsyncFunctionCompleted : public ScriptFunction { public: static v8::Local<v8::Function> CreateFunction(ScriptState* script_state, - ThreadPoolTask* task, + Task* task, State state) { return (new AsyncFunctionCompleted(script_state, task, state)) ->BindToV8Function(); @@ -32,50 +33,47 @@ } private: - AsyncFunctionCompleted(ScriptState* script_state, - ThreadPoolTask* task, - State state) + AsyncFunctionCompleted(ScriptState* script_state, Task* task, State state) : ScriptFunction(script_state), task_(task), state_(state) {} - ThreadPoolTask* task_; + CrossThreadPersistent<Task> task_; const State state_; }; -ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider, - ScriptState* script_state, - const ScriptValue& function, - const Vector<ScriptValue>& arguments, - TaskType task_type) - : ThreadPoolTask(thread_provider, - script_state, - function, - String(), - arguments, - task_type) {} +Task::Task(ThreadPoolThreadProvider* thread_provider, + ScriptState* script_state, + const ScriptValue& function, + const Vector<ScriptValue>& arguments, + TaskType task_type) + : Task(thread_provider, + script_state, + function, + String(), + arguments, + task_type) {} -ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider, - ScriptState* script_state, - const String& function_name, - const Vector<ScriptValue>& arguments, - TaskType task_type) - : ThreadPoolTask(thread_provider, - script_state, - ScriptValue(), - function_name, - arguments, - task_type) {} +Task::Task(ThreadPoolThreadProvider* thread_provider, + ScriptState* script_state, + const String& function_name, + const Vector<ScriptValue>& arguments, + TaskType task_type) + : Task(thread_provider, + script_state, + ScriptValue(), + function_name, + arguments, + task_type) {} -ThreadPoolTask::ThreadPoolTask(ThreadPoolThreadProvider* thread_provider, - ScriptState* script_state, - const ScriptValue& function, - const String& function_name, - const Vector<ScriptValue>& arguments, - TaskType task_type) +Task::Task(ThreadPoolThreadProvider* thread_provider, + ScriptState* script_state, + const ScriptValue& function, + const String& function_name, + const Vector<ScriptValue>& arguments, + TaskType task_type) : task_type_(task_type), - self_keep_alive_(base::AdoptRef(this)), + self_keep_alive_(this), resolver_(ScriptPromiseResolver::Create(script_state)), function_name_(function_name.IsolatedCopy()), - arguments_(arguments.size()), - weak_factory_(this) { + arguments_(arguments.size()) { DCHECK(IsMainThread()); DCHECK_EQ(!function.IsEmpty(), function_name.IsNull()); DCHECK(task_type_ == TaskType::kUserInteraction || @@ -88,7 +86,7 @@ isolate, function.V8Value()->ToString(isolate)); } - Vector<ThreadPoolTask*> prerequisites; + HeapVector<Member<Task>> prerequisites; Vector<size_t> prerequisites_indices; for (size_t i = 0; i < arguments_.size(); i++) { // Normal case: if the argument isn't a Task, just serialize it. @@ -98,10 +96,9 @@ isolate, arguments[i].V8Value()); continue; } - ThreadPoolTask* prerequisite = + Task* prerequisite = ToScriptWrappable(arguments[i].V8Value().As<v8::Object>()) - ->ToImpl<Task>() - ->GetThreadPoolTask(); + ->ToImpl<Task>(); prerequisites.push_back(prerequisite); prerequisites_indices.push_back(i); } @@ -114,7 +111,7 @@ return; } - // Prior to this point, other ThreadPoolTask instances don't have a reference + // Prior to this point, other Task instances don't have a reference // to |this| yet, so no need to lock mutex_. RegisterDependencies() populates // those references, so RegisterDependencies() and any logic thereafter must // consider the potential for data races. @@ -122,14 +119,14 @@ } // static -ThreadPoolThread* ThreadPoolTask::SelectThread( - const Vector<ThreadPoolTask*>& prerequisites, +ThreadPoolThread* Task::SelectThread( + const HeapVector<Member<Task>>& prerequisites, ThreadPoolThreadProvider* thread_provider) { DCHECK(IsMainThread()); HashCountedSet<ThreadPoolThread*> prerequisite_location_counts; size_t max_prerequisite_location_count = 0; ThreadPoolThread* max_prerequisite_thread = nullptr; - for (ThreadPoolTask* prerequisite : prerequisites) { + for (Task* prerequisite : prerequisites) { // For prerequisites that are not yet complete, track which thread the task // will run on. Put this task on the thread where the most prerequisites // reside. This is slightly imprecise, because a task may complete before @@ -147,7 +144,7 @@ : thread_provider->GetLeastBusyThread(); } -ThreadPoolThread* ThreadPoolTask::GetScheduledThread() { +ThreadPoolThread* Task::GetScheduledThread() { DCHECK(IsMainThread()); MutexLocker lock(mutex_); return HasFinished() ? nullptr : worker_thread_; @@ -155,9 +152,8 @@ // Should only be called from constructor. Split out in to a helper because // clang appears to exempt constructors from thread safety analysis. -void ThreadPoolTask::RegisterDependencies( - const Vector<ThreadPoolTask*>& prerequisites, - const Vector<size_t>& prerequisites_indices) { +void Task::RegisterDependencies(const HeapVector<Member<Task>>& prerequisites, + const Vector<size_t>& prerequisites_indices) { DCHECK(IsMainThread()); { MutexLocker lock(mutex_); @@ -165,7 +161,7 @@ } for (size_t i = 0; i < prerequisites.size(); i++) { - ThreadPoolTask* prerequisite = prerequisites[i]; + Task* prerequisite = prerequisites[i]; size_t prerequisite_index = prerequisites_indices[i]; scoped_refptr<SerializedScriptValue> result; State prerequisite_state = State::kPending; @@ -176,8 +172,8 @@ if (prerequisite->HasFinished()) { result = prerequisite->serialized_result_; } else { - prerequisite->dependents_.insert( - std::make_unique<Dependent>(this, prerequisite_index)); + prerequisite->dependents_.emplace_back( + new Dependent(this, prerequisite_index)); } } @@ -191,7 +187,7 @@ } } -ThreadPoolTask::~ThreadPoolTask() { +Task::~Task() { DCHECK(IsMainThread()); DCHECK(HasFinished()); DCHECK(!function_); @@ -200,11 +196,10 @@ DCHECK(dependents_.IsEmpty()); } -void ThreadPoolTask::PrerequisiteFinished( - size_t prerequisite_index, - v8::Local<v8::Value> v8_result, - scoped_refptr<SerializedScriptValue> result, - State prerequisite_state) { +void Task::PrerequisiteFinished(size_t prerequisite_index, + v8::Local<v8::Value> v8_result, + scoped_refptr<SerializedScriptValue> result, + State prerequisite_state) { MutexLocker lock(mutex_); DCHECK(state_ == State::kPending || state_ == State::kCancelPending); DCHECK(prerequisite_state == State::kCompleted || @@ -225,16 +220,16 @@ MaybeStartTask(); } -void ThreadPoolTask::MaybeStartTask() { +void Task::MaybeStartTask() { if (prerequisites_remaining_) return; DCHECK(state_ == State::kPending || state_ == State::kCancelPending); PostCrossThreadTask(*worker_thread_->GetTaskRunner(task_type_), FROM_HERE, - CrossThreadBind(&ThreadPoolTask::StartTaskOnWorkerThread, - CrossThreadUnretained(this))); + CrossThreadBind(&Task::StartTaskOnWorkerThread, + WrapCrossThreadPersistent(this))); } -void ThreadPoolTask::StartTaskOnWorkerThread() { +void Task::StartTaskOnWorkerThread() { DCHECK(worker_thread_->IsCurrentThread()); bool was_cancelled = false; @@ -269,9 +264,8 @@ RunTaskOnWorkerThread(); } -void ThreadPoolTask::TaskCompletedOnWorkerThread( - v8::Local<v8::Value> return_value, - State state) { +void Task::TaskCompletedOnWorkerThread(v8::Local<v8::Value> return_value, + State state) { DCHECK(worker_thread_->IsCurrentThread()); scoped_refptr<SerializedScriptValue> local_result = @@ -281,7 +275,7 @@ function_ = nullptr; arguments_.clear(); - HashSet<std::unique_ptr<Dependent>> dependents_to_notify; + Vector<CrossThreadPersistent<Dependent>> dependents_to_notify; { MutexLocker lock(mutex_); serialized_result_ = local_result; @@ -298,12 +292,10 @@ *worker_thread_->GetParentExecutionContextTaskRunners()->Get( TaskType::kInternalWorker), FROM_HERE, - CrossThreadBind(&ThreadPoolTask::TaskCompleted, - CrossThreadUnretained(this))); - // TaskCompleted may delete |this| at any time after this point. + CrossThreadBind(&Task::TaskCompleted, WrapCrossThreadPersistent(this))); } -void ThreadPoolTask::RunTaskOnWorkerThread() { +void Task::RunTaskOnWorkerThread() { DCHECK(worker_thread_->IsCurrentThread()); // No other thread should be touching function_ or arguments_ at this point, // so no mutex needed while actually running the task. @@ -378,7 +370,7 @@ TaskCompletedOnWorkerThread(return_value, State::kCompleted); } -void ThreadPoolTask::TaskCompleted() { +void Task::TaskCompleted() { DCHECK(IsMainThread()); bool rejected = false; { @@ -401,23 +393,22 @@ resolver_->Resolve(value); } worker_thread_->DecrementTasksInProgressCount(); - self_keep_alive_.reset(); - // |this| may be deleted here. + self_keep_alive_.Clear(); } -ScriptPromise ThreadPoolTask::GetResult() { +ScriptPromise Task::result() { DCHECK(IsMainThread()); return resolver_->Promise(); } -void ThreadPoolTask::Cancel() { +void Task::cancel() { DCHECK(IsMainThread()); MutexLocker lock(mutex_); if (state_ == State::kPending) AdvanceState(State::kCancelPending); } -void ThreadPoolTask::AdvanceState(State new_state) { +void Task::AdvanceState(State new_state) { switch (new_state) { case State::kPending: NOTREACHED() << "kPending should only be set via initialization"; @@ -438,4 +429,9 @@ state_ = new_state; } +void Task::Trace(Visitor* visitor) { + ScriptWrappable::Trace(visitor); + visitor->Trace(resolver_); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/experimental/task.h b/third_party/blink/renderer/core/workers/experimental/task.h index 2294cf7..eb51f822 100644 --- a/third_party/blink/renderer/core/workers/experimental/task.h +++ b/third_party/blink/renderer/core/workers/experimental/task.h
@@ -18,41 +18,40 @@ // Scans |arguments| for Task objects, and registers those as dependencies, // passing the result of those tasks in place of the Task arguments. // All public functions are main-thread-only. -// ThreadPoolTask keeps itself alive via a self scoped_refptr until the +// Task keeps itself alive via a SelfKeepAlive until the // the task completes and reports itself done on the main thread via -// TaskCompleted(). Other users (e.g. Task below) can keep the task -// alive after completion. -class ThreadPoolTask final : public RefCounted<ThreadPoolTask> { +// TaskCompleted(). +class Task final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + public: // Called on main thread - ThreadPoolTask(ThreadPoolThreadProvider*, - ScriptState*, - const ScriptValue& function, - const Vector<ScriptValue>& arguments, - TaskType); - ThreadPoolTask(ThreadPoolThreadProvider*, - ScriptState*, - const String& function_name, - const Vector<ScriptValue>& arguments, - TaskType); - ~ThreadPoolTask(); + Task(ThreadPoolThreadProvider*, + ScriptState*, + const ScriptValue& function, + const Vector<ScriptValue>& arguments, + TaskType); + Task(ThreadPoolThreadProvider*, + ScriptState*, + const String& function_name, + const Vector<ScriptValue>& arguments, + TaskType); + ~Task() override; // Returns a promise that will be resolved with the result when it completes. - ScriptPromise GetResult(); - void Cancel() LOCKS_EXCLUDED(mutex_); + ScriptPromise result(); + void cancel() LOCKS_EXCLUDED(mutex_); - base::WeakPtr<ThreadPoolTask> GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } + void Trace(Visitor*) override; private: enum class State { kPending, kStarted, kCancelPending, kCompleted, kFailed }; - ThreadPoolTask(ThreadPoolThreadProvider*, - ScriptState*, - const ScriptValue& function, - const String& function_name, - const Vector<ScriptValue>& arguments, - TaskType); + Task(ThreadPoolThreadProvider*, + ScriptState*, + const ScriptValue& function, + const String& function_name, + const Vector<ScriptValue>& arguments, + TaskType); class AsyncFunctionCompleted; @@ -74,10 +73,10 @@ // Called on main thread static ThreadPoolThread* SelectThread( - const Vector<ThreadPoolTask*>& prerequisites, + const HeapVector<Member<Task>>& prerequisites, ThreadPoolThreadProvider*); ThreadPoolThread* GetScheduledThread() LOCKS_EXCLUDED(mutex_); - void RegisterDependencies(const Vector<ThreadPoolTask*>& prerequisites, + void RegisterDependencies(const HeapVector<Member<Task>>& prerequisites, const Vector<size_t>& prerequisite_indices) LOCKS_EXCLUDED(mutex_); void TaskCompleted(); @@ -87,8 +86,8 @@ const TaskType task_type_; // Main thread only - scoped_refptr<ThreadPoolTask> self_keep_alive_; - Persistent<ScriptPromiseResolver> resolver_; + SelfKeepAlive<Task> self_keep_alive_; + Member<ScriptPromiseResolver> resolver_; // Created in constructor on the main thread, consumed and cleared on // worker_thread_. Those steps can't overlap, so no mutex_ required. @@ -120,38 +119,20 @@ size_t prerequisites_remaining_ GUARDED_BY(mutex_) = 0u; // Elements added from main thread. Cleared on completion on worker_thread_. - // Each element in dependents_ is not yet in the kCompleted state and - // therefore is guaranteed to be alive. - struct Dependent { + // Each element in dependents_ is not yet in the kCompleted state. + struct Dependent final : public GarbageCollected<Dependent> { public: - Dependent(ThreadPoolTask* task, size_t index) : task(task), index(index) {} - ThreadPoolTask* task; + Dependent(Task* task, size_t index) : task(task), index(index) { + DCHECK(IsMainThread()); + } + void Trace(Visitor* visitor) { visitor->Trace(task); } + Member<Task> task; + // The index in the dependent's argument array where this result should go. size_t index; }; - HashSet<std::unique_ptr<Dependent>> dependents_ GUARDED_BY(mutex_); + Vector<CrossThreadPersistent<Dependent>> dependents_ GUARDED_BY(mutex_); Mutex mutex_; - - base::WeakPtrFactory<ThreadPoolTask> weak_factory_; -}; - -// This is a thin, v8-exposed wrapper around ThreadPoolTask that allows -// ThreadPoolTask to avoid being GarbageCollected. -class Task : public ScriptWrappable { - DEFINE_WRAPPERTYPEINFO(); - - public: - explicit Task(ThreadPoolTask* thread_pool_task) - : thread_pool_task_(thread_pool_task) {} - ~Task() override = default; - - ScriptPromise result() { return thread_pool_task_->GetResult(); } - void cancel() { thread_pool_task_->Cancel(); } - - ThreadPoolTask* GetThreadPoolTask() const { return thread_pool_task_.get(); } - - private: - scoped_refptr<ThreadPoolTask> thread_pool_task_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc index 70bb5eb..8cdafe2 100644 --- a/third_party/blink/renderer/core/workers/experimental/task_worklet.cc +++ b/third_party/blink/renderer/core/workers/experimental/task_worklet.cc
@@ -55,17 +55,14 @@ // TODO(japhet): Here and below: it's unclear what task type should be used, // and whether the API should allow it to be configured. Using kIdleTask as a // placeholder for now. - ThreadPoolTask* thread_pool_task = new ThreadPoolTask( - this, script_state, function, arguments, TaskType::kIdleTask); - return new Task(thread_pool_task); + return new Task(this, script_state, function, arguments, TaskType::kIdleTask); } Task* TaskWorklet::postTask(ScriptState* script_state, const String& function_name, const Vector<ScriptValue>& arguments) { - ThreadPoolTask* thread_pool_task = new ThreadPoolTask( - this, script_state, function_name, arguments, TaskType::kIdleTask); - return new Task(thread_pool_task); + return new Task(this, script_state, function_name, arguments, + TaskType::kIdleTask); } ThreadPoolThread* TaskWorklet::GetLeastBusyThread() {
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc index 7faaa50e..112024eb 100644 --- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc +++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.cc
@@ -39,19 +39,17 @@ ScriptPromise WorkerTaskQueue::postFunction( ScriptState* script_state, - const ScriptValue& task, + const ScriptValue& function, AbortSignal* signal, const Vector<ScriptValue>& arguments) { DCHECK(document_->IsContextThread()); - DCHECK(task.IsFunction()); + DCHECK(function.IsFunction()); - ThreadPoolTask* thread_pool_task = new ThreadPoolTask( - ThreadPool::From(*document_), script_state, task, arguments, task_type_); - if (signal) { - signal->AddAlgorithm( - WTF::Bind(&ThreadPoolTask::Cancel, thread_pool_task->GetWeakPtr())); - } - return thread_pool_task->GetResult(); + Task* task = new Task(ThreadPool::From(*document_), script_state, function, + arguments, task_type_); + if (signal) + signal->AddAlgorithm(WTF::Bind(&Task::cancel, WrapWeakPersistent(task))); + return task->result(); } Task* WorkerTaskQueue::postTask(ScriptState* script_state, @@ -59,11 +57,8 @@ const Vector<ScriptValue>& arguments) { DCHECK(document_->IsContextThread()); DCHECK(function.IsFunction()); - - ThreadPoolTask* thread_pool_task = - new ThreadPoolTask(ThreadPool::From(*document_), script_state, function, - arguments, task_type_); - return new Task(thread_pool_task); + return new Task(ThreadPool::From(*document_), script_state, function, + arguments, task_type_); } void WorkerTaskQueue::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h index 6eb29b67..0872c73a 100644 --- a/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h +++ b/third_party/blink/renderer/core/workers/experimental/worker_task_queue.h
@@ -30,12 +30,12 @@ ~WorkerTaskQueue() override = default; ScriptPromise postFunction(ScriptState*, - const ScriptValue& task, + const ScriptValue& function, AbortSignal*, const Vector<ScriptValue>& arguments); Task* postTask(ScriptState*, - const ScriptValue& task, + const ScriptValue& function, const Vector<ScriptValue>& arguments); void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc index 35f122c..0be0583b 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.cc +++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -435,7 +435,6 @@ const base::Optional<WorkerBackingThreadStartupData>& thread_startup_data, std::unique_ptr<WorkerDevToolsParams> devtools_params) { DCHECK(IsCurrentThread()); - bool wait_for_debugger = devtools_params->wait_for_debugger; { MutexLocker lock(mutex_); DCHECK_EQ(ThreadState::kNotStarted, thread_state_); @@ -492,11 +491,7 @@ // Otherwise, InspectorTaskRunner might interrupt isolate execution // from another thread and try to resume "pause on start" before // we even paused. - if (wait_for_debugger) { - WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(GetIsolate()); - if (debugger) - debugger->PauseWorkerOnStart(this); - } + worker_inspector_controller_->WaitForDebuggerIfNeeded(); } void WorkerThread::EvaluateClassicScriptOnWorkerThread(
diff --git a/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js b/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js index a0ad048..ae4dd41 100644 --- a/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js +++ b/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
@@ -71,7 +71,7 @@ return jsonView; const dataURL = Common.ContentProvider.contentAsDataURL( - contentData.content, this.request.mimeType, contentData.encoded, contentData.encoded ? 'utf-8' : null); + contentData.content, this.request.mimeType, contentData.encoded, this.request.charset()); return dataURL ? new Network.RequestHTMLView(dataURL) : null; }
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js b/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js index e097ea2..b5e4223 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
@@ -1245,6 +1245,24 @@ this._backendRequestId = requestId; this._requestId = requestId; } + + /** + * @return {?string} + */ + charset() { + const contentTypeHeader = this.responseHeaderValue('content-type'); + if (!contentTypeHeader) + return null; + + const responseCharsets = contentTypeHeader.replace(/ /g, '') + .split(';') + .filter(parameter => parameter.toLowerCase().startsWith('charset=')) + .map(parameter => parameter.slice('charset='.length)); + if (responseCharsets.length) + return responseCharsets[0]; + + return null; + } }; /** @enum {symbol} */
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/third_party/blink/renderer/modules/background_sync/sync_manager.cc index 21b8bb98..67ca01c 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.cc +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -40,8 +40,6 @@ mojom::blink::SyncRegistrationPtr sync_registration = mojom::blink::SyncRegistration::New(); sync_registration->tag = tag; - sync_registration->network_state = - blink::mojom::BackgroundSyncNetworkState::ONLINE; GetBackgroundSyncServicePtr()->Register( std::move(sync_registration), registration_->RegistrationId(),
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn index fb4d8b6..00f60af 100644 --- a/third_party/blink/renderer/modules/mediastream/BUILD.gn +++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -28,8 +28,6 @@ "media_stream_track_content_hint.h", "media_stream_track_event.cc", "media_stream_track_event.h", - "navigator_display_media.cc", - "navigator_display_media.h", "navigator_media_stream.cc", "navigator_media_stream.h", "navigator_user_media.cc",
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc index 456bc1f..baea7b1 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.cc +++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -158,6 +158,15 @@ return promise; } +ScriptPromise MediaDevices::getDisplayMedia( + ScriptState* script_state, + const MediaStreamConstraints* options, + ExceptionState& exception_state) { + return SendUserMediaRequest(script_state, + WebUserMediaRequest::MediaType::kDisplayMedia, + options, exception_state); +} + const AtomicString& MediaDevices::InterfaceName() const { return event_target_names::kMediaDevices; }
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.h b/third_party/blink/renderer/modules/mediastream/media_devices.h index a9465cb3..00ea279 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.h +++ b/third_party/blink/renderer/modules/mediastream/media_devices.h
@@ -50,6 +50,10 @@ const MediaStreamConstraints*, ExceptionState&); + ScriptPromise getDisplayMedia(ScriptState*, + const MediaStreamConstraints*, + ExceptionState&); + // EventTarget overrides. const AtomicString& InterfaceName() const override; ExecutionContext* GetExecutionContext() const override;
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.idl b/third_party/blink/renderer/modules/mediastream/media_devices.idl index c37a6b2..15f1f88 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.idl +++ b/third_party/blink/renderer/modules/mediastream/media_devices.idl
@@ -10,10 +10,17 @@ ActiveScriptWrappable ] interface MediaDevices : EventTarget { [RuntimeEnabled=OnDeviceChange] attribute EventHandler ondevicechange; - [CallWith=ScriptState, MeasureAs=MediaDevicesEnumerateDevices] Promise<sequence<MediaDeviceInfo>> enumerateDevices(); + [ + CallWith = ScriptState, MeasureAs = MediaDevicesEnumerateDevices + ] Promise<sequence<MediaDeviceInfo>> + enumerateDevices(); MediaTrackSupportedConstraints getSupportedConstraints(); - [CallWith=ScriptState, - RaisesException, - MeasureAs=GetUserMediaPromise - ] Promise<MediaStream> getUserMedia(optional MediaStreamConstraints constraints); + [ + CallWith = ScriptState, RaisesException, MeasureAs = GetUserMediaPromise + ] Promise<MediaStream> + getUserMedia(optional MediaStreamConstraints constraints); + [ + RuntimeEnabled = GetDisplayMedia, CallWith = ScriptState, RaisesException + ] Promise<MediaStream> + getDisplayMedia(optional MediaStreamConstraints constraints); };
diff --git a/third_party/blink/renderer/modules/mediastream/navigator_display_media.cc b/third_party/blink/renderer/modules/mediastream/navigator_display_media.cc deleted file mode 100644 index 7ec54bd8..0000000 --- a/third_party/blink/renderer/modules/mediastream/navigator_display_media.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2018 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/modules/mediastream/navigator_display_media.h" - -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" -#include "third_party/blink/renderer/core/dom/dom_exception.h" -#include "third_party/blink/renderer/modules/mediastream/media_devices.h" -#include "third_party/blink/renderer/modules/mediastream/navigator_user_media.h" - -namespace blink { - -ScriptPromise NavigatorDisplayMedia::getDisplayMedia( - ScriptState* script_state, - Navigator& navigator, - const MediaStreamConstraints* options, - ExceptionState& exception_state) { - MediaDevices* const media_devices = - NavigatorUserMedia::mediaDevices(navigator); - if (!media_devices) { - return ScriptPromise::RejectWithDOMException( - script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError, - "Current frame is detached.")); - } - - return media_devices->SendUserMediaRequest( - script_state, WebUserMediaRequest::MediaType::kDisplayMedia, options, - exception_state); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/navigator_display_media.h b/third_party/blink/renderer/modules/mediastream/navigator_display_media.h deleted file mode 100644 index dfe03d6..0000000 --- a/third_party/blink/renderer/modules/mediastream/navigator_display_media.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2018 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_MODULES_MEDIASTREAM_NAVIGATOR_DISPLAY_MEDIA_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_NAVIGATOR_DISPLAY_MEDIA_H_ - -#include "third_party/blink/renderer/platform/wtf/allocator.h" - -#include "third_party/blink/renderer/core/frame/navigator.h" - -namespace blink { - -class ExceptionState; -class MediaStreamConstraints; -class ScriptPromise; -class ScriptState; - -class NavigatorDisplayMedia { - STATIC_ONLY(NavigatorDisplayMedia); - - public: - static ScriptPromise getDisplayMedia(ScriptState*, - Navigator&, - const MediaStreamConstraints*, - ExceptionState&); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_NAVIGATOR_DISPLAY_MEDIA_H_
diff --git a/third_party/blink/renderer/modules/mediastream/navigator_display_media.idl b/third_party/blink/renderer/modules/mediastream/navigator_display_media.idl deleted file mode 100644 index 8afdc7e..0000000 --- a/third_party/blink/renderer/modules/mediastream/navigator_display_media.idl +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2018 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. - -// https://w3c.github.io/mediacapture-screen-share/ -[ - ImplementedAs = NavigatorDisplayMedia, - RuntimeEnabled = GetDisplayMedia -] partial interface Navigator { - [CallWith = ScriptState, RaisesException] Promise<MediaStream> - getDisplayMedia(optional MediaStreamConstraints constraints); -};
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index d02a51d..ac02a900 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -765,7 +765,6 @@ "mediasource/url_media_source.idl", "mediasource/video_track_source_buffer.idl", "mediastream/media_stream_track_content_hint.idl", - "mediastream/navigator_display_media.idl", "mediastream/navigator_media_stream.idl", "mediastream/navigator_user_media.idl", "mediastream/window_media_stream.idl",
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index a209128..75dee62 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -103,11 +103,11 @@ event_target_names::kModulesNamesCount + indexed_db_names::kNamesCount; StringImpl::ReserveStaticStringsCapacityForSize(kModulesStaticStringsCount); - event_interface_names::initModules(); - event_target_names::initModules(); + event_interface_names::InitModules(); + event_target_names::InitModules(); Document::RegisterEventFactory(EventModulesFactory::Create()); ModuleBindingsInitializer::Init(); - indexed_db_names::init(); + indexed_db_names::Init(); AXObjectCache::Init(AXObjectCacheImpl::Create); DraggedIsolatedFileSystem::Init( DraggedIsolatedFileSystemImpl::PrepareForDataObject);
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc index 618e7b96..fbe1e072d 100644 --- a/third_party/blink/renderer/platform/exported/platform.cc +++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -195,10 +195,10 @@ ThreadState::AttachMainThread(); - // FontFamilyNames are used by platform/fonts and are initialized by core. + // font_family_names are used by platform/fonts and are initialized by core. // In case core is not available (like on PPAPI plugins), we need to init // them here. - font_family_names::init(); + font_family_names::Init(); InitializePlatformLanguage(); DCHECK(!g_gc_task_runner);
diff --git a/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc b/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc index a35c5dc..5f03b58 100644 --- a/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc +++ b/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
@@ -39,8 +39,7 @@ FontDescription chinese; chinese.SetLocale(LayoutLocale::Get("zh")); - if (font_family_names::kWebkitStandard.IsEmpty()) - font_family_names::init(); + font_family_names::Init(); // For non-CJK, getGenericFamilyNameForScript should return the given // familyName.
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 38b4148d..dff767f 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -377,7 +377,11 @@ } void GraphicsLayer::UpdateChildList() { - // TODO(pdr): Do not attach cc::Layers when using layer lists. + // When using layer lists, cc::Layers are created in PaintArtifactCompositor. + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) { + return; + } cc::Layer* child_host = layer_.get(); child_host->RemoveAllChildren();
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/third_party/blink/renderer/platform/testing/testing_platform_support.cc index 42cad57..a9d9b23b 100644 --- a/third_party/blink/renderer/platform/testing/testing_platform_support.cc +++ b/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -186,11 +186,11 @@ ThreadState::AttachMainThread(); ThreadState::Current()->RegisterTraceDOMWrappers(nullptr, nullptr, nullptr, nullptr); - http_names::init(); - fetch_initiator_type_names::init(); + http_names::Init(); + fetch_initiator_type_names::Init(); InitializePlatformLanguage(); - font_family_names::init(); + font_family_names::Init(); WebRuntimeFeatures::EnableExperimentalFeatures(true); WebRuntimeFeatures::EnableTestOnlyFeatures(true); }
diff --git a/third_party/unrar/src/global.cpp b/third_party/unrar/src/global.cpp index 4eebac1b..3975813a 100644 --- a/third_party/unrar/src/global.cpp +++ b/third_party/unrar/src/global.cpp
@@ -1,9 +1,7 @@ #define INCLUDEGLOBAL -#if !defined(CHROMIUM_UNRAR) #if defined(__BORLANDC__) || defined(_MSC_VER) #pragma hdrstop #endif -#endif // defined(CHROMIUM_UNRAR) #include "rar.hpp"
diff --git a/tools/cygprofile/profile_android_startup.py b/tools/cygprofile/profile_android_startup.py index fc75e81..e18adf1 100755 --- a/tools/cygprofile/profile_android_startup.py +++ b/tools/cygprofile/profile_android_startup.py
@@ -264,6 +264,7 @@ logging.info('Using pregenerated profiles instead of running profile') logging.info('Profile files: %s', '\n'.join(self._pregenerated_profiles)) return self._pregenerated_profiles + self._device.adb.Logcat(clear=True) self._Install(apk) try: changer = self._SetChromeFlags(package_info) @@ -274,6 +275,11 @@ self._RunProfileCollection(package_info, self._simulate_user) else: self._RunProfileCollection(package_info, self._simulate_user) + except device_errors.CommandFailedError as exc: + logging.error('Exception %s; dumping logcat', exc) + for logcat_line in self._device.adb.Logcat(dump=True): + logging.error(logcat_line) + raise finally: self._RestoreChromeFlags(changer)
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index 30a24416..4227a83 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -33,6 +33,12 @@ 'mr_extension/release', ], + 'linux_component': [ + # https://crbug.com/900696 + 'browser_tests.isolated', + 'remoting-webapp.v2.zip', + ], + # https://crbug.com/330262 'mac': [ # ld64 in current Xcode versions is not deterministic. Most smaller binaries
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 12878da..d8b5863 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -612,6 +612,7 @@ 'linux-blink-gen-property-trees': 'release_trybot', 'linux-blink-heap-incremental-marking': 'debug_trybot_enable_blink_heap_incremental_marking', 'linux-blink-heap-verification-try': 'release_trybot_enable_blink_heap_verification', + 'linux-coverage-rel': 'clang_code_coverage_trybot', 'linux-dcheck-off-rel': 'release_trybot_dcheck_off', 'linux-goma-rbe-staging-rel': 'gpu_tests_release_trybot_no_symbols', 'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11', @@ -1090,6 +1091,10 @@ 'release_bot', 'clang', 'use_clang_coverage', 'no_symbols', ], + 'clang_code_coverage_trybot': [ + 'gpu_tests', 'use_dummy_lastchange', 'release_trybot', 'clang', 'use_clang_coverage', 'no_symbols', + ], + 'clang_release_bot_minimal_symbols_x86': [ 'clang', 'release_bot', 'minimal_symbols', 'x86', ],
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0b286d7..e48923e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -8263,6 +8263,9 @@ <histogram name="BackgroundFetch.RegistrationCreatedError" enum="BackgroundFetchError"> + <obsolete> + Deprecated 10/2018 since DB tasks record this more accurately. + </obsolete> <owner>peter@chromium.org</owner> <owner>rayankans@chromium.org</owner> <summary> @@ -8273,6 +8276,9 @@ <histogram name="BackgroundFetch.RegistrationDeletedError" enum="BackgroundFetchError"> + <obsolete> + Deprecated 10/2018 since DB tasks record this more accurately. + </obsolete> <owner>peter@chromium.org</owner> <owner>rayankans@chromium.org</owner> <summary> @@ -8283,6 +8289,9 @@ <histogram name="BackgroundFetch.SchedulerFinishedError" enum="BackgroundFetchError"> + <obsolete> + Deprecated 10/2018 since DB tasks record this more accurately. + </obsolete> <owner>peter@chromium.org</owner> <owner>rayankans@chromium.org</owner> <summary> @@ -59538,6 +59547,15 @@ </summary> </histogram> +<histogram name="Net.QuicStreamFactory.MigrationBeforeHandshake" + enum="BooleanSuccess" expires_after="2020-11-01"> + <owner>zhongyi@chromium.org</owner> + <summary> + Status of the connection which is created for migration before handshake is + confirmed. + </summary> +</histogram> + <histogram name="Net.QuicStreamFactory.PublicResetsPostHandshake" units="resets"> <owner>ckrasic@chromium.org</owner> @@ -124691,7 +124709,7 @@ <suffix name="ClickEvent" label="BackgroundFetchClickEvent"/> <suffix name="FailEvent" label="BackgroundFetchFailEvent"/> <suffix name="FetchedEvent" label="BackgroundFetchedEvent"/> - <suffix name="FetchSuccessEvent" label="BackgroundFetchSuccessEvent"/> + <suffix name="SuccessEvent" label="BackgroundFetchSuccessEvent"/> <affected-histogram name="BackgroundFetch.EventDispatchFailure.Dispatch"/> <affected-histogram name="BackgroundFetch.EventDispatchFailure.FindWorker"/> <affected-histogram name="BackgroundFetch.EventDispatchFailure.StartWorker"/>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 9bcaf51..9c094e8 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -140,6 +140,7 @@ crbug.com/901510 [ Nexus_5 ] memory.long_running_idle_gmail_tbmv2/* [ Skip ] crbug.com/901510 [ Nexus5X_Webview ] memory.long_running_idle_gmail_tbmv2/* [ Skip ] crbug.com/901510 [ Nexus_5X ] memory.long_running_idle_gmail_tbmv2/* [ Skip ] +crbug.com/902064 [ Nexus_5 ] memory.long_running_idle_gmail_background_tbmv2/* [ Skip ] # Benchmark: memory.long_running_idle_gmail_background_tbmv2 crbug.com/611167 [ Android_Svelte ] memory.long_running_idle_gmail_background_tbmv2/* [ Skip ] @@ -353,6 +354,7 @@ crbug.com/853212 [ Android_Webview ] v8.browsing_mobile/browse:news:cnn [ Skip ] crbug.com/877648 [ Android_Go ] v8.browsing_mobile/browse:news:toi [ Skip ] crbug.com/877648 [ Android_Go ] v8.browsing_mobile/browse:news:cnn [ Skip ] +crbug.com/901967 [ Nexus6_Webview ] v8.browsing_mobile/browse:news:toi [ Skip ] # Benchmark: v8.browsing_mobile-future crbug.com/900909 [ Android ] v8.browsing_mobile-future/browse:chrome:omnibox [ Skip ] @@ -367,6 +369,7 @@ crbug.com/799080 [ Nexus_5X Android_Webview ] v8.browsing_mobile-future/browse:social:facebook [ Skip ] crbug.com/875159 [ Win_10 ] v8.browsing_desktop-future/browse:social:facebook_infinite_scroll [ Skip ] crbug.com/901534 [ Nexus6_Webview ] v8.browsing_mobile-future/browse:news:toi [ Skip ] +crbug.com/902064 [ Nexus_5 ] v8.browsing_mobile-future/browse:news:toi [ Skip ] # Benchmark: v8.detached_context_age_in_gc crbug.com/770982 [ Win ] v8.detached_context_age_in_gc/Docs_(1_open_document_tab) [ Skip ]
diff --git a/ui/file_manager/integration_tests/file_manager/metadata.js b/ui/file_manager/integration_tests/file_manager/metadata.js index 7b5bcd2..fd0841e1 100644 --- a/ui/file_manager/integration_tests/file_manager/metadata.js +++ b/ui/file_manager/integration_tests/file_manager/metadata.js
@@ -13,10 +13,19 @@ * @return {boolean} */ function equal1PercentMargin(value, desiredValue) { - const minValue = desiredValue * 0.99; - const maxValue = desiredValue * 1.01; - return value === desiredValue || - (minValue <= desiredValue && desiredValue <= maxValue); + // floor and ceil to account to at least +/-1 unit. + const minValue = Math.floor(desiredValue * 0.99); + const maxValue = Math.ceil(desiredValue * 1.01); + + const result = + value === desiredValue || (minValue <= value && value <= maxValue); + if (!result) { + console.log( + 'min value: ' + minValue + ' got value: ' + value + + ' max value: ' + maxValue); + } + + return result; } /** @@ -188,7 +197,8 @@ // + 8 files in Downloads again. // = 21 chrome.test.assertEq(21, metadataStats.fullFetch); - // 8 files and 3 folders in Downloads when expading in the directory tree. + // 8 files and 3 folders in Downloads when expanding in the directory + // tree. chrome.test.assertEq(0, metadataStats.fromCache); // Cleared 8 files + 3 folders when navigated out of Downloads and // clearing file list. @@ -256,8 +266,8 @@ result &= equal1PercentMargin(metadataStats.fullFetch, 103); // 50 team drives cached, reading from file list when navigating to - // /team_drives, then read cached when expading directory tree. - result &= equal1PercentMargin(metadataStats.fromCache, 62); + // /team_drives, then read cached when expanding directory tree. + result &= metadataStats.fromCache < 70; // Cleared 51 folders when navigated out of My Drive and clearing file // list. @@ -363,7 +373,7 @@ // = 152 chrome.test.assertEq(152, metadataStats.fullFetch); // 50 team drives cached, reading from file list when navigating to - // /team_drives, then read cached when expading directory tree. + // /team_drives, then read cached when expanding directory tree. chrome.test.assertEq(50, metadataStats.fromCache); // Cleared 50 folders + 50 files when navigated out of My Drive and // clearing file list.
diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h index 19dce397..a84f55d 100644 --- a/ui/gl/gl_version_info.h +++ b/ui/gl/gl_version_info.h
@@ -42,6 +42,12 @@ return is_es || IsAtLeastGL(4, 1); } + // We need to emulate GL_ALPHA and GL_LUMINANCE and GL_LUMINANCE_ALPHA + // texture formats on core profile and ES3, except for ANGLE and Swiftshader. + bool NeedsLuminanceAlphaEmulation() const { + return !is_angle && !is_swiftshader && (is_es3 || is_desktop_core_profile); + } + bool is_es; bool is_angle; bool is_d3d;
diff --git a/ui/views/accessibility/ax_aura_obj_cache.cc b/ui/views/accessibility/ax_aura_obj_cache.cc index 5811bf2..7c840f0 100644 --- a/ui/views/accessibility/ax_aura_obj_cache.cc +++ b/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -208,7 +208,7 @@ return Get(it->second); auto wrapper = std::make_unique<AuraViewWrapper>(aura_view); - int32_t id = wrapper->GetUniqueId().Get(); + int32_t id = wrapper->GetUniqueId(); aura_view_to_id_map[aura_view] = id; cache_[id] = std::move(wrapper); return cache_[id].get();
diff --git a/ui/views/accessibility/ax_aura_obj_wrapper.h b/ui/views/accessibility/ax_aura_obj_wrapper.h index fa0f7954..5ce9d6c31 100644 --- a/ui/views/accessibility/ax_aura_obj_wrapper.h +++ b/ui/views/accessibility/ax_aura_obj_wrapper.h
@@ -17,7 +17,6 @@ namespace ui { struct AXActionData; struct AXNodeData; -class AXUniqueId; } // namespace ui namespace views { @@ -36,7 +35,7 @@ virtual void GetChildren( std::vector<AXAuraObjWrapper*>* out_children) = 0; virtual void Serialize(ui::AXNodeData* out_node_data) = 0; - virtual const ui::AXUniqueId& GetUniqueId() const = 0; + virtual int32_t GetUniqueId() const = 0; // Actions. virtual bool HandleAccessibleAction(const ui::AXActionData& action);
diff --git a/ui/views/accessibility/ax_root_obj_wrapper.cc b/ui/views/accessibility/ax_root_obj_wrapper.cc index 8f16302..c9327cbb 100644 --- a/ui/views/accessibility/ax_root_obj_wrapper.cc +++ b/ui/views/accessibility/ax_root_obj_wrapper.cc
@@ -10,6 +10,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/platform/ax_unique_id.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/display/display.h" @@ -98,8 +99,8 @@ #endif } -const ui::AXUniqueId& AXRootObjWrapper::GetUniqueId() const { - return unique_id_; +int32_t AXRootObjWrapper::GetUniqueId() const { + return unique_id_.Get(); } void AXRootObjWrapper::OnDisplayMetricsChanged(const display::Display& display,
diff --git a/ui/views/accessibility/ax_root_obj_wrapper.h b/ui/views/accessibility/ax_root_obj_wrapper.h index f90f9853..7f0ca125 100644 --- a/ui/views/accessibility/ax_root_obj_wrapper.h +++ b/ui/views/accessibility/ax_root_obj_wrapper.h
@@ -37,7 +37,7 @@ void GetChildren( std::vector<views::AXAuraObjWrapper*>* out_children) override; void Serialize(ui::AXNodeData* out_node_data) override; - const ui::AXUniqueId& GetUniqueId() const override; + int32_t GetUniqueId() const override; private: // display::DisplayObserver:
diff --git a/ui/views/accessibility/ax_tree_source_views.cc b/ui/views/accessibility/ax_tree_source_views.cc index cffc41f..5caa7c73 100644 --- a/ui/views/accessibility/ax_tree_source_views.cc +++ b/ui/views/accessibility/ax_tree_source_views.cc
@@ -38,20 +38,20 @@ tree_data->loading_progress = 1.0; AXAuraObjWrapper* focus = AXAuraObjCache::GetInstance()->GetFocus(); if (focus) - tree_data->focus_id = focus->GetUniqueId().Get(); + tree_data->focus_id = focus->GetUniqueId(); return true; } AXAuraObjWrapper* AXTreeSourceViews::GetFromId(int32_t id) const { AXAuraObjWrapper* root = GetRoot(); // Root might not be in the cache. - if (id == root->GetUniqueId().Get()) + if (id == root->GetUniqueId()) return root; return AXAuraObjCache::GetInstance()->Get(id); } int32_t AXTreeSourceViews::GetId(AXAuraObjWrapper* node) const { - return node->GetUniqueId().Get(); + return node->GetUniqueId(); } void AXTreeSourceViews::GetChildren( @@ -100,7 +100,7 @@ ui::AXNodeData parent_data; parent->Serialize(&parent_data); out_data->location.Offset(-parent_data.location.OffsetFromOrigin()); - out_data->offset_container_id = parent->GetUniqueId().Get(); + out_data->offset_container_id = parent->GetUniqueId(); } std::string AXTreeSourceViews::ToString(AXAuraObjWrapper* root,
diff --git a/ui/views/accessibility/ax_tree_source_views_unittest.cc b/ui/views/accessibility/ax_tree_source_views_unittest.cc index e0b06cc..acfcdf2 100644 --- a/ui/views/accessibility/ax_tree_source_views_unittest.cc +++ b/ui/views/accessibility/ax_tree_source_views_unittest.cc
@@ -109,16 +109,16 @@ EXPECT_EQ(root, tree.GetParent(textfield)); // IDs match the ones in the cache. - EXPECT_EQ(root->GetUniqueId().Get(), tree.GetId(root)); - EXPECT_EQ(label1->GetUniqueId().Get(), tree.GetId(label1)); - EXPECT_EQ(label2->GetUniqueId().Get(), tree.GetId(label2)); - EXPECT_EQ(textfield->GetUniqueId().Get(), tree.GetId(textfield)); + EXPECT_EQ(root->GetUniqueId(), tree.GetId(root)); + EXPECT_EQ(label1->GetUniqueId(), tree.GetId(label1)); + EXPECT_EQ(label2->GetUniqueId(), tree.GetId(label2)); + EXPECT_EQ(textfield->GetUniqueId(), tree.GetId(textfield)); // Reverse ID lookups work. - EXPECT_EQ(root, tree.GetFromId(root->GetUniqueId().Get())); - EXPECT_EQ(label1, tree.GetFromId(label1->GetUniqueId().Get())); - EXPECT_EQ(label2, tree.GetFromId(label2->GetUniqueId().Get())); - EXPECT_EQ(textfield, tree.GetFromId(textfield->GetUniqueId().Get())); + EXPECT_EQ(root, tree.GetFromId(root->GetUniqueId())); + EXPECT_EQ(label1, tree.GetFromId(label1->GetUniqueId())); + EXPECT_EQ(label2, tree.GetFromId(label2->GetUniqueId())); + EXPECT_EQ(textfield, tree.GetFromId(textfield->GetUniqueId())); // Validity. EXPECT_TRUE(tree.IsValid(root));
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.cc b/ui/views/accessibility/ax_view_obj_wrapper.cc index 1009ec6..d8c900e 100644 --- a/ui/views/accessibility/ax_view_obj_wrapper.cc +++ b/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -6,6 +6,7 @@ #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/platform/ax_unique_id.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/view.h" @@ -16,15 +17,24 @@ AXViewObjWrapper::AXViewObjWrapper(View* view) : view_(view) { if (view->GetWidget()) AXAuraObjCache::GetInstance()->GetOrCreate(view->GetWidget()); + view->AddObserver(this); } -AXViewObjWrapper::~AXViewObjWrapper() {} +AXViewObjWrapper::~AXViewObjWrapper() { + if (view_) { + view_->RemoveObserver(this); + view_ = nullptr; + } +} bool AXViewObjWrapper::IsIgnored() { - return view_->GetViewAccessibility().IsIgnored(); + return view_ ? view_->GetViewAccessibility().IsIgnored() : true; } AXAuraObjWrapper* AXViewObjWrapper::GetParent() { + if (!view_) + return nullptr; + AXAuraObjCache* cache = AXAuraObjCache::GetInstance(); if (view_->parent()) return cache->GetOrCreate(view_->parent()); @@ -37,6 +47,9 @@ void AXViewObjWrapper::GetChildren( std::vector<AXAuraObjWrapper*>* out_children) { + if (!view_) + return; + if (view_->GetViewAccessibility().IsLeaf()) return; @@ -52,16 +65,23 @@ } void AXViewObjWrapper::Serialize(ui::AXNodeData* out_node_data) { + if (!view_) + return; + view_->GetViewAccessibility().GetAccessibleNodeData(out_node_data); - out_node_data->id = GetUniqueId().Get(); + out_node_data->id = GetUniqueId(); } -const ui::AXUniqueId& AXViewObjWrapper::GetUniqueId() const { - return view_->GetViewAccessibility().GetUniqueId(); +int32_t AXViewObjWrapper::GetUniqueId() const { + return view_ ? view_->GetViewAccessibility().GetUniqueId() : -1; } bool AXViewObjWrapper::HandleAccessibleAction(const ui::AXActionData& action) { - return view_->HandleAccessibleAction(action); + return view_ ? view_->HandleAccessibleAction(action) : false; +} + +void AXViewObjWrapper::OnViewIsDeleting(View* observed_view) { + view_ = nullptr; } } // namespace views
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.h b/ui/views/accessibility/ax_view_obj_wrapper.h index eff142fc..5a16030 100644 --- a/ui/views/accessibility/ax_view_obj_wrapper.h +++ b/ui/views/accessibility/ax_view_obj_wrapper.h
@@ -9,12 +9,13 @@ #include "base/macros.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" +#include "ui/views/view_observer.h" namespace views { class View; // Describes a |View| for use with other AX classes. -class AXViewObjWrapper : public AXAuraObjWrapper { +class AXViewObjWrapper : public AXAuraObjWrapper, public ViewObserver { public: explicit AXViewObjWrapper(View* view); ~AXViewObjWrapper() override; @@ -26,11 +27,14 @@ AXAuraObjWrapper* GetParent() override; void GetChildren(std::vector<AXAuraObjWrapper*>* out_children) override; void Serialize(ui::AXNodeData* out_node_data) override; - const ui::AXUniqueId& GetUniqueId() const final; + int32_t GetUniqueId() const final; bool HandleAccessibleAction(const ui::AXActionData& action) override; + // ViewObserver overrides. + void OnViewIsDeleting(View* observed_view) override; + private: - View* const view_; + View* view_; DISALLOW_COPY_AND_ASSIGN(AXViewObjWrapper); };
diff --git a/ui/views/accessibility/ax_widget_obj_wrapper.cc b/ui/views/accessibility/ax_widget_obj_wrapper.cc index 0192ff9f..096d2ea4 100644 --- a/ui/views/accessibility/ax_widget_obj_wrapper.cc +++ b/ui/views/accessibility/ax_widget_obj_wrapper.cc
@@ -46,7 +46,7 @@ } void AXWidgetObjWrapper::Serialize(ui::AXNodeData* out_node_data) { - out_node_data->id = GetUniqueId().Get(); + out_node_data->id = GetUniqueId(); out_node_data->role = widget_->widget_delegate()->GetAccessibleWindowRole(); out_node_data->AddStringAttribute( ax::mojom::StringAttribute::kName, @@ -56,8 +56,8 @@ out_node_data->state = 0; } -const ui::AXUniqueId& AXWidgetObjWrapper::GetUniqueId() const { - return unique_id_; +int32_t AXWidgetObjWrapper::GetUniqueId() const { + return unique_id_.Get(); } void AXWidgetObjWrapper::OnWidgetDestroying(Widget* widget) {
diff --git a/ui/views/accessibility/ax_widget_obj_wrapper.h b/ui/views/accessibility/ax_widget_obj_wrapper.h index 5110cfe5..283efcb7 100644 --- a/ui/views/accessibility/ax_widget_obj_wrapper.h +++ b/ui/views/accessibility/ax_widget_obj_wrapper.h
@@ -29,7 +29,7 @@ AXAuraObjWrapper* GetParent() override; void GetChildren(std::vector<AXAuraObjWrapper*>* out_children) override; void Serialize(ui::AXNodeData* out_node_data) override; - const ui::AXUniqueId& GetUniqueId() const final; + int32_t GetUniqueId() const final; // WidgetObserver overrides. void OnWidgetDestroying(Widget* widget) override;
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.cc b/ui/views/accessibility/ax_window_obj_wrapper.cc index cd77dabf..5809af7 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.cc +++ b/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -11,7 +11,6 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/accessibility/platform/aura_window_properties.h" -#include "ui/accessibility/platform/ax_unique_id.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/window.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" @@ -85,7 +84,7 @@ } void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) { - out_node_data->id = GetUniqueId().Get(); + out_node_data->id = GetUniqueId(); ax::mojom::Role role = window_->GetProperty(ui::kAXRoleOverride); if (role != ax::mojom::Role::kNone) out_node_data->role = role; @@ -116,8 +115,8 @@ } } -const ui::AXUniqueId& AXWindowObjWrapper::GetUniqueId() const { - return unique_id_; +int32_t AXWindowObjWrapper::GetUniqueId() const { + return unique_id_.Get(); } void AXWindowObjWrapper::OnWindowDestroyed(aura::Window* window) {
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.h b/ui/views/accessibility/ax_window_obj_wrapper.h index e996fa3..716b95f 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.h +++ b/ui/views/accessibility/ax_window_obj_wrapper.h
@@ -36,7 +36,7 @@ AXAuraObjWrapper* GetParent() override; void GetChildren(std::vector<AXAuraObjWrapper*>* out_children) override; void Serialize(ui::AXNodeData* out_node_data) override; - const ui::AXUniqueId& GetUniqueId() const final; + int32_t GetUniqueId() const final; // WindowObserver overrides. void OnWindowDestroyed(aura::Window* window) override;
diff --git a/ui/views/linux_ui/linux_ui.h b/ui/views/linux_ui/linux_ui.h index 759d4ab..208c9a5 100644 --- a/ui/views/linux_ui/linux_ui.h +++ b/ui/views/linux_ui/linux_ui.h
@@ -130,10 +130,12 @@ // Checks for platform support for status icons. virtual bool IsStatusIconSupported() const = 0; - // Create a native status icon. + // Create a native status icon. The id_prefix is used to distinguish Chrome's + // status icons from other apps' status icons, and should be unique. virtual std::unique_ptr<StatusIconLinux> CreateLinuxStatusIcon( const gfx::ImageSkia& image, - const base::string16& tool_tip) const = 0; + const base::string16& tool_tip, + const char* id_prefix) const = 0; // Returns the icon for a given content type from the icon theme. // TODO(davidben): Add an observer for the theme changing, so we can drop the
diff --git a/ui/views/mus/ax_remote_host.cc b/ui/views/mus/ax_remote_host.cc index e2fcba76..89ea463 100644 --- a/ui/views/mus/ax_remote_host.cc +++ b/ui/views/mus/ax_remote_host.cc
@@ -247,7 +247,7 @@ } ui::AXEvent event; - event.id = aura_obj->GetUniqueId().Get(); + event.id = aura_obj->GetUniqueId(); event.event_type = event_type; // Other fields are not used.
diff --git a/ui/views/mus/ax_tree_source_mus_unittest.cc b/ui/views/mus/ax_tree_source_mus_unittest.cc index b4fbdd5..ed907eb6 100644 --- a/ui/views/mus/ax_tree_source_mus_unittest.cc +++ b/ui/views/mus/ax_tree_source_mus_unittest.cc
@@ -86,7 +86,7 @@ // Child has relative position with the root as the container. EXPECT_EQ(gfx::RectF(1, 1, 111, 111), node_data.location); - EXPECT_EQ(root->GetUniqueId().Get(), node_data.offset_container_id); + EXPECT_EQ(root->GetUniqueId(), node_data.offset_container_id); } TEST_F(AXTreeSourceMusTest, ScaleFactor) {
diff --git a/webrunner/cipd/castrunner.yaml b/webrunner/cipd/castrunner.yaml new file mode 100644 index 0000000..43cb0fc --- /dev/null +++ b/webrunner/cipd/castrunner.yaml
@@ -0,0 +1,33 @@ +# Copyright 2018 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. + +# Creates a package for the Cast application Runner. +# Note that the web.ContextProvider package is required by the Cast Runner. +# The ID of the target architecture (amd64, arm64) must be passed in as +# a pkg-var so that the packages can be archived at the appropriate location +# in the CIPD package hierarchy. +# +# pkg-var arguments: +# outdir: A fully qualified path to the build output directory. +# targetarch: The target architecture, either "amd64" or "arm64". +# +# To create a CIPD package, run the following command from the build output +# directory. +# +# $ cipd create --pkg-def ../../webrunner/cipd/castrunner.yaml \ +# -pkg-var targetarch:$TARGET_ARCH \ +# -pkg-var outdir:`pwd` \ +# -ref latest \ +# -tag version:$(cat fuchsia_artifacts/build_id.txt) +# +# The most recent package can be discovered by searching for the "latest" ref: +# +# $ cipd describe chromium/fuchsia/castrunner-$TARGET_ARCH -version latest + +package: chromium/fuchsia/castrunner-${targetarch} +description: Prebuilt Cast application Runner binaries for Fuchsia. +root: ${outdir}/fuchsia_artifacts +data: + - file: cast_runner.far + - file: LICENSE